From c29dc2d771411850777eb027756b12106b5f6cd5 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 18 Mar 2013 15:33:39 +0800 Subject: [PATCH 001/169] net: fec: handle optional clk_ptp more gracefully When the optional clk_ptp is absent, we can just set it to NULL, and clk API will just handle it gracefully. It saves us from checking clk_ptp whenever calling into clk API. Also since clk_ptp is optional, the "ret" variable shouldn't be set in case that the clock is absent. Signed-off-by: Shawn Guo Acked-by: David S. Miller --- drivers/net/ethernet/freescale/fec.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index 911d0253dbb2..6d965bb32908 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c @@ -1806,14 +1806,13 @@ fec_probe(struct platform_device *pdev) fep->bufdesc_ex = pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX; if (IS_ERR(fep->clk_ptp)) { - ret = PTR_ERR(fep->clk_ptp); + fep->clk_ptp = NULL; fep->bufdesc_ex = 0; } clk_prepare_enable(fep->clk_ahb); clk_prepare_enable(fep->clk_ipg); - if (!IS_ERR(fep->clk_ptp)) - clk_prepare_enable(fep->clk_ptp); + clk_prepare_enable(fep->clk_ptp); reg_phy = devm_regulator_get(&pdev->dev, "phy"); if (!IS_ERR(reg_phy)) { @@ -1878,8 +1877,7 @@ failed_irq: failed_regulator: clk_disable_unprepare(fep->clk_ahb); clk_disable_unprepare(fep->clk_ipg); - if (!IS_ERR(fep->clk_ptp)) - clk_disable_unprepare(fep->clk_ptp); + clk_disable_unprepare(fep->clk_ptp); failed_pin: failed_clk: iounmap(fep->hwp); From daa7d392ffe67e698ee442694276061624b4b0a1 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 29 Jan 2013 15:46:11 +0100 Subject: [PATCH 002/169] net: freescale: fec: add support for optional enet_out clk Some MX28 boards need the internal enet_out clock to be enabled. So, do this in the driver iff the clock was referenced via devicetree. Signed-off-by: Wolfram Sang Signed-off-by: Shawn Guo Acked-by: David S. Miller --- drivers/net/ethernet/freescale/fec.c | 10 ++++++++++ drivers/net/ethernet/freescale/fec.h | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index 6d965bb32908..dd098ea44d48 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c @@ -1802,6 +1802,11 @@ fec_probe(struct platform_device *pdev) goto failed_clk; } + /* enet_out is optional, depends on board */ + fep->clk_enet_out = devm_clk_get(&pdev->dev, "enet_out"); + if (IS_ERR(fep->clk_enet_out)) + fep->clk_enet_out = NULL; + fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp"); fep->bufdesc_ex = pdev->id_entry->driver_data & FEC_QUIRK_HAS_BUFDESC_EX; @@ -1812,6 +1817,7 @@ fec_probe(struct platform_device *pdev) clk_prepare_enable(fep->clk_ahb); clk_prepare_enable(fep->clk_ipg); + clk_prepare_enable(fep->clk_enet_out); clk_prepare_enable(fep->clk_ptp); reg_phy = devm_regulator_get(&pdev->dev, "phy"); @@ -1877,6 +1883,7 @@ failed_irq: failed_regulator: clk_disable_unprepare(fep->clk_ahb); clk_disable_unprepare(fep->clk_ipg); + clk_disable_unprepare(fep->clk_enet_out); clk_disable_unprepare(fep->clk_ptp); failed_pin: failed_clk: @@ -1903,6 +1910,7 @@ fec_drv_remove(struct platform_device *pdev) clk_disable_unprepare(fep->clk_ptp); if (fep->ptp_clock) ptp_clock_unregister(fep->ptp_clock); + clk_disable_unprepare(fep->clk_enet_out); clk_disable_unprepare(fep->clk_ahb); clk_disable_unprepare(fep->clk_ipg); for (i = 0; i < FEC_IRQ_NUM; i++) { @@ -1933,6 +1941,7 @@ fec_suspend(struct device *dev) fec_stop(ndev); netif_device_detach(ndev); } + clk_disable_unprepare(fep->clk_enet_out); clk_disable_unprepare(fep->clk_ahb); clk_disable_unprepare(fep->clk_ipg); @@ -1945,6 +1954,7 @@ fec_resume(struct device *dev) struct net_device *ndev = dev_get_drvdata(dev); struct fec_enet_private *fep = netdev_priv(ndev); + clk_prepare_enable(fep->clk_enet_out); clk_prepare_enable(fep->clk_ahb); clk_prepare_enable(fep->clk_ipg); if (netif_running(ndev)) { diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index eb4372962839..feabcb6a78b4 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -207,6 +207,7 @@ struct fec_enet_private { struct clk *clk_ipg; struct clk *clk_ahb; + struct clk *clk_enet_out; struct clk *clk_ptp; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ From f231a9fe7f802962ac225e56c91597680e282186 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 29 Jan 2013 15:46:12 +0100 Subject: [PATCH 003/169] ARM: dts: mxs: add enet_out clock to devicetree Put the clock to the devicetree, so the driver can take care of it later. Then, we don't have to do the enabling as a workaround in board init. Signed-off-by: Wolfram Sang [shawn.guo: add enet_out into imx28.dtsi and overwrite it for m28evk] Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx28-m28evk.dts | 2 ++ arch/arm/boot/dts/imx28.dtsi | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts index 6ce3d17c3a29..3d2e1a491335 100644 --- a/arch/arm/boot/dts/imx28-m28evk.dts +++ b/arch/arm/boot/dts/imx28-m28evk.dts @@ -221,6 +221,8 @@ phy-mode = "rmii"; pinctrl-names = "default"; pinctrl-0 = <&mac0_pins_a>; + clocks = <&clks 57>, <&clks 57>; + clock-names = "ipg", "ahb"; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi index 64af2381c1b0..9a7adaa4e4fb 100644 --- a/arch/arm/boot/dts/imx28.dtsi +++ b/arch/arm/boot/dts/imx28.dtsi @@ -943,8 +943,8 @@ compatible = "fsl,imx28-fec"; reg = <0x800f0000 0x4000>; interrupts = <101>; - clocks = <&clks 57>, <&clks 57>; - clock-names = "ipg", "ahb"; + clocks = <&clks 57>, <&clks 57>, <&clks 64>; + clock-names = "ipg", "ahb", "enet_out"; status = "disabled"; }; From d260a7af0fbd2257b3d88b3e72b8b11a0398f796 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 18 Mar 2013 15:59:24 +0800 Subject: [PATCH 004/169] ARM: mxs: remove unneeded enet_out clk initialization With fec driver taking care of enet_out clk, most of board setup do not need to enable enet_out clk. So remove them. Signed-off-by: Shawn Guo --- arch/arm/mach-mxs/mach-mxs.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index 16870bf853b8..6a4e11824ec9 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c @@ -360,7 +360,6 @@ static inline void enable_clk_enet_out(void) static void __init imx28_evk_init(void) { - enable_clk_enet_out(); update_fec_mac_prop(OUI_FSL); mxsfb_pdata.mode_list = mx28evk_video_modes; @@ -391,11 +390,6 @@ static void __init m28evk_init(void) mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT; } -static void __init sc_sps1_init(void) -{ - enable_clk_enet_out(); -} - static int apx4devkit_phy_fixup(struct phy_device *phy) { phy->dev_flags |= MICREL_PHY_50MHZ_CLK; @@ -494,7 +488,6 @@ static void __init tx28_post_init(void) static void __init cfa10049_init(void) { - enable_clk_enet_out(); update_fec_mac_prop(OUI_CRYSTALFONTZ); mxsfb_pdata.mode_list = cfa10049_video_modes; @@ -506,14 +499,11 @@ static void __init cfa10049_init(void) static void __init cfa10037_init(void) { - enable_clk_enet_out(); update_fec_mac_prop(OUI_CRYSTALFONTZ); } static void __init apf28_init(void) { - enable_clk_enet_out(); - mxsfb_pdata.mode_list = apf28dev_video_modes; mxsfb_pdata.mode_count = ARRAY_SIZE(apf28dev_video_modes); mxsfb_pdata.default_bpp = 16; @@ -538,8 +528,6 @@ static void __init mxs_machine_init(void) cfa10049_init(); else if (of_machine_is_compatible("armadeus,imx28-apf28")) apf28_init(); - else if (of_machine_is_compatible("schulercontrol,imx28-sps1")) - sc_sps1_init(); of_platform_populate(NULL, of_default_bus_match_table, mxs_auxdata_lookup, NULL); From 9e5485791b805e3235ba5fb53d140881dbbe79be Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 13 Mar 2013 13:37:11 +0800 Subject: [PATCH 005/169] video: mxsfb: use devm_* managed functions Use devm_* managed functions to make code a little cleaner. Signed-off-by: Shawn Guo --- drivers/video/mxsfb.c | 50 ++++++++++++++----------------------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 45169cbaba6e..69fb3f1d1e12 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -802,23 +802,19 @@ static int mxsfb_probe(struct platform_device *pdev) return -ENODEV; } - if (!request_mem_region(res->start, resource_size(res), pdev->name)) - return -EBUSY; - fb_info = framebuffer_alloc(sizeof(struct mxsfb_info), &pdev->dev); if (!fb_info) { dev_err(&pdev->dev, "Failed to allocate fbdev\n"); - ret = -ENOMEM; - goto error_alloc_info; + return -ENOMEM; } host = to_imxfb_host(fb_info); - host->base = ioremap(res->start, resource_size(res)); - if (!host->base) { + host->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(host->base)) { dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENOMEM; - goto error_ioremap; + ret = PTR_ERR(host->base); + goto fb_release; } host->pdev = pdev; @@ -829,13 +825,13 @@ static int mxsfb_probe(struct platform_device *pdev) pinctrl = devm_pinctrl_get_select_default(&pdev->dev); if (IS_ERR(pinctrl)) { ret = PTR_ERR(pinctrl); - goto error_getpin; + goto fb_release; } - host->clk = clk_get(&host->pdev->dev, NULL); + host->clk = devm_clk_get(&host->pdev->dev, NULL); if (IS_ERR(host->clk)) { ret = PTR_ERR(host->clk); - goto error_getclock; + goto fb_release; } panel_enable = of_get_named_gpio_flags(pdev->dev.of_node, @@ -850,14 +846,15 @@ static int mxsfb_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to request gpio %d: %d\n", panel_enable, ret); - goto error_panel_enable; + goto fb_release; } } - fb_info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); + fb_info->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16, + GFP_KERNEL); if (!fb_info->pseudo_palette) { ret = -ENOMEM; - goto error_pseudo_pallette; + goto fb_release; } INIT_LIST_HEAD(&fb_info->modelist); @@ -866,7 +863,7 @@ static int mxsfb_probe(struct platform_device *pdev) ret = mxsfb_init_fbinfo(host); if (ret != 0) - goto error_init_fb; + goto fb_release; for (i = 0; i < pdata->mode_count; i++) fb_add_videomode(&pdata->mode_list[i], &fb_info->modelist); @@ -883,7 +880,7 @@ static int mxsfb_probe(struct platform_device *pdev) ret = register_framebuffer(fb_info); if (ret != 0) { dev_err(&pdev->dev,"Failed to register framebuffer\n"); - goto error_register; + goto fb_destroy; } if (!host->enabled) { @@ -896,22 +893,12 @@ static int mxsfb_probe(struct platform_device *pdev) return 0; -error_register: +fb_destroy: if (host->enabled) clk_disable_unprepare(host->clk); fb_destroy_modelist(&fb_info->modelist); -error_init_fb: - kfree(fb_info->pseudo_palette); -error_pseudo_pallette: -error_panel_enable: - clk_put(host->clk); -error_getclock: -error_getpin: - iounmap(host->base); -error_ioremap: +fb_release: framebuffer_release(fb_info); -error_alloc_info: - release_mem_region(res->start, resource_size(res)); return ret; } @@ -920,19 +907,14 @@ static int mxsfb_remove(struct platform_device *pdev) { struct fb_info *fb_info = platform_get_drvdata(pdev); struct mxsfb_info *host = to_imxfb_host(fb_info); - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (host->enabled) mxsfb_disable_controller(fb_info); unregister_framebuffer(fb_info); - kfree(fb_info->pseudo_palette); mxsfb_free_videomem(host); - iounmap(host->base); - clk_put(host->clk); framebuffer_release(fb_info); - release_mem_region(res->start, resource_size(res)); platform_set_drvdata(pdev, NULL); From 4aa02c7cbb6816913554dc18ff750a70a4ace796 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 13 Mar 2013 14:03:12 +0800 Subject: [PATCH 006/169] video: mxsfb: remove fb_phys/fb_size from platform_data There is no in-tree users of mxsfb_platform_data fb_phys/fb_size. With CMA support in the kernel, there is no real need for platform to reserve memory and pass address and size into driver via platform_data. So let's remove fb_phys/fb_size from mxsfb_platform_data to ease full device tree adoption. Signed-off-by: Shawn Guo --- drivers/video/mxsfb.c | 39 +++++++-------------------------------- include/linux/mxsfb.h | 9 --------- 2 files changed, 7 insertions(+), 41 deletions(-) diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 69fb3f1d1e12..9e8740bade32 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -168,7 +168,6 @@ struct mxsfb_info { unsigned ld_intf_width; unsigned dotclk_delay; const struct mxsfb_devdata *devdata; - int mapped; u32 sync; }; @@ -686,7 +685,7 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host) struct mxsfb_platform_data *pdata = host->pdev->dev.platform_data; dma_addr_t fb_phys; void *fb_virt; - unsigned fb_size = pdata->fb_size; + unsigned fb_size; fb_info->fbops = &mxsfb_ops; fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST; @@ -706,30 +705,12 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host) host->ld_intf_width = pdata->ld_intf_width; /* Memory allocation for framebuffer */ - if (pdata->fb_phys) { - if (!fb_size) - return -EINVAL; + fb_size = SZ_2M; + fb_virt = alloc_pages_exact(fb_size, GFP_DMA); + if (!fb_virt) + return -ENOMEM; - fb_phys = pdata->fb_phys; - - if (!request_mem_region(fb_phys, fb_size, host->pdev->name)) - return -ENOMEM; - - fb_virt = ioremap(fb_phys, fb_size); - if (!fb_virt) { - release_mem_region(fb_phys, fb_size); - return -ENOMEM; - } - host->mapped = 1; - } else { - if (!fb_size) - fb_size = SZ_2M; /* default */ - fb_virt = alloc_pages_exact(fb_size, GFP_DMA); - if (!fb_virt) - return -ENOMEM; - - fb_phys = virt_to_phys(fb_virt); - } + fb_phys = virt_to_phys(fb_virt); fb_info->fix.smem_start = fb_phys; fb_info->screen_base = fb_virt; @@ -745,13 +726,7 @@ static void mxsfb_free_videomem(struct mxsfb_info *host) { struct fb_info *fb_info = &host->fb_info; - if (host->mapped) { - iounmap(fb_info->screen_base); - release_mem_region(fb_info->fix.smem_start, - fb_info->screen_size); - } else { - free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len); - } + free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len); } static struct platform_device_id mxsfb_devtype[] = { diff --git a/include/linux/mxsfb.h b/include/linux/mxsfb.h index f80af8674342..93696404ee55 100644 --- a/include/linux/mxsfb.h +++ b/include/linux/mxsfb.h @@ -35,15 +35,6 @@ struct mxsfb_platform_data { unsigned dotclk_delay; /* refer manual HW_LCDIF_VDCTRL4 register */ unsigned ld_intf_width; /* refer STMLCDIF_* macros */ - - unsigned fb_size; /* Size of the video memory. If zero a - * default will be used - */ - unsigned long fb_phys; /* physical address for the video memory. If - * zero the framebuffer memory will be dynamically - * allocated. If specified,fb_size must also be specified. - * fb_phys must be unused by Linux. - */ u32 sync; /* sync mask, contains MXSFB specifics not * carried in fb_info->var.sync */ From 36f3e99649baa77b2d22e385b2ea09e8f308c905 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 13 Mar 2013 14:28:19 +0800 Subject: [PATCH 007/169] video: mxsfb: remove dotclk_delay from platform_data There is no in-tree mxsfb users using mxsfb_platform_data dotclk_delay. Let's remove it from mxsfb_platform_data to ease full device tree adoption of mxsfb driver. If later we have platform/board need to configure this parameter, we can add it into device tree bindings. Signed-off-by: Shawn Guo --- drivers/video/mxsfb.c | 1 - include/linux/mxsfb.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 9e8740bade32..a89901c7f5e9 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -701,7 +701,6 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host) var->accel_flags = 0; var->vmode = FB_VMODE_NONINTERLACED; - host->dotclk_delay = pdata->dotclk_delay; host->ld_intf_width = pdata->ld_intf_width; /* Memory allocation for framebuffer */ diff --git a/include/linux/mxsfb.h b/include/linux/mxsfb.h index 93696404ee55..b78465cdb26e 100644 --- a/include/linux/mxsfb.h +++ b/include/linux/mxsfb.h @@ -33,7 +33,6 @@ struct mxsfb_platform_data { unsigned default_bpp; - unsigned dotclk_delay; /* refer manual HW_LCDIF_VDCTRL4 register */ unsigned ld_intf_width; /* refer STMLCDIF_* macros */ u32 sync; /* sync mask, contains MXSFB specifics not * carried in fb_info->var.sync From 669406534b4abb827d1bdc39bb5e2d5255818ae2 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 14 Mar 2013 10:57:34 +0800 Subject: [PATCH 008/169] video: mxsfb: get display timings from device tree Use videomode helpers to get display timings and configurations from device tree when platform_data is absent. Signed-off-by: Shawn Guo --- .../devicetree/bindings/fb/mxsfb.txt | 34 +++++ drivers/video/Kconfig | 2 + drivers/video/mxsfb.c | 122 ++++++++++++++++-- 3 files changed, 146 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/fb/mxsfb.txt b/Documentation/devicetree/bindings/fb/mxsfb.txt index b41e5e52a676..7ba3b7663513 100644 --- a/Documentation/devicetree/bindings/fb/mxsfb.txt +++ b/Documentation/devicetree/bindings/fb/mxsfb.txt @@ -5,10 +5,20 @@ Required properties: imx23 and imx28. - reg: Address and length of the register set for lcdif - interrupts: Should contain lcdif interrupts +- display : phandle to display node (see below for details) Optional properties: - panel-enable-gpios : Should specify the gpio for panel enable +* display node + +Required properties: +- bits-per-pixel : <16> for RGB565, <32> for RGB888/666. +- bus-width : number of data lines. Could be <8>, <16>, <18> or <24>. + +Required sub-node: +- display-timings : Refer to binding doc display-timing.txt for details. + Examples: lcdif@80030000 { @@ -16,4 +26,28 @@ lcdif@80030000 { reg = <0x80030000 2000>; interrupts = <38 86>; panel-enable-gpios = <&gpio3 30 0>; + + display: display { + bits-per-pixel = <32>; + bus-width = <24>; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <33500000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <164>; + hback-porch = <89>; + hsync-len = <10>; + vback-porch = <23>; + vfront-porch = <10>; + vsync-len = <10>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <0>; + }; + }; + }; }; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 4c1546f71d56..e7718fdad1e1 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2437,6 +2437,8 @@ config FB_MXS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select FB_MODE_HELPERS + select OF_VIDEOMODE help Framebuffer support for the MXS SoC. diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index a89901c7f5e9..e5ceba54d22f 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -43,12 +43,14 @@ #include #include #include +#include