[PATCH 00/23] OMAPDSS: Create output entities
Create a new entity in OMAPDSS called outputs. These represent the interfaces/outputs like DSI, HDMI etc. that a panel connects to. An output sits in between an overlay manager and a panel. More details about outputs are explained in the first patch of the series. This series adds omap_dss_output as an entity along with omap_overlay, omap_overlay_manager and omap_dss_device. It changes the code to establish links between managers and outputs, and outputs and devices. The rest of the patches replace omap_dss_device with omap_dss_output as the argument exposed by interface driver functions(DSI, HDMI etc) for panel drivers. Reference tree: git://gitorious.org/~boddob/linux-omap-dss2/archit-dss2-clone.git 2-add-outputs Archit Taneja (23): OMAPDSS: outputs: Create a new entity called outputs OMAPDSS: outputs: Create and initialize output instances OMAPDSS: output: Add set/unset device ops for omap_dss_output OMAPDSS: APPLY: Add manager set/unset output ops for omap_overlay_manager OMAPDSS: Remove manager-device references OMAP_VOUT: Remove manager-device references OMAPFB: remove manager-device references OMAPDRM: Remove manager-device references OMAPDSS: Create links between managers, outputs and devices OMAPDSS: DPI: Pass outputs from panel driver to DPI interface driver OMAPDSS: DSI: Remove dsi_pdev_map global struct OMAPDSS: DSI: Pass outputs from panel driver to DSI interface driver OMAPDSS: SDI: Pass outputs from panel driver to SDI interface driver OMAPDSS: RFBI: Pass outputs from panel driver to RFBI interface driver OMAPDSS: RFBI: Add output pointers as arguments to all exported functions OMAPDSS: VENC: Pass outputs from panel driver to VENC interface driver OMAPDSS: HDMI: Pass outputs from panel driver to HDMI interface driver OMAPDSS: HDMI: Add output pointers as arguments to all functions used by hdmi panel driver OMAPDSS/OMAPFB: Change dssdev-manager references OMAPDSS: MANAGER: Update display sysfs store OMAPDSS: MANAGER: Get device via output OMAPDSS: APPLY: Remove omap_dss_device references from dss_ovl_enable/disable OMAPDSS: Remove old way of setting manager and device links drivers/media/video/omap/omap_vout.c | 81 -- drivers/staging/omapdrm/omap_drv.c |5 +- drivers/video/omap2/displays/panel-acx565akm.c | 22 +- drivers/video/omap2/displays/panel-generic-dpi.c | 27 +- .../omap2/displays/panel-lgphilips-lb035q02.c | 16 +- drivers/video/omap2/displays/panel-n8x0.c | 114 +--- .../omap2/displays/panel-nec-nl8048hl11-01b.c | 15 +- drivers/video/omap2/displays/panel-picodlp.c | 15 +- .../video/omap2/displays/panel-sharp-ls037v7dw01.c | 16 +- drivers/video/omap2/displays/panel-taal.c | 201 - drivers/video/omap2/displays/panel-tfp410.c| 17 +- .../video/omap2/displays/panel-tpo-td043mtea1.c| 29 +- drivers/video/omap2/dss/Makefile |2 +- drivers/video/omap2/dss/apply.c| 52 ++-- drivers/video/omap2/dss/core.c |1 + drivers/video/omap2/dss/dispc.c| 10 +- drivers/video/omap2/dss/display.c | 11 +- drivers/video/omap2/dss/dpi.c | 84 -- drivers/video/omap2/dss/dsi.c | 307 +++- drivers/video/omap2/dss/dss.h | 50 ++-- drivers/video/omap2/dss/dss_features.c | 52 drivers/video/omap2/dss/dss_features.h |1 + drivers/video/omap2/dss/hdmi.c | 84 -- drivers/video/omap2/dss/hdmi_panel.c | 85 -- drivers/video/omap2/dss/manager.c | 48 ++- drivers/video/omap2/dss/output.c | 125 drivers/video/omap2/dss/overlay.c | 96 +++--- drivers/video/omap2/dss/rfbi.c | 77 +++-- drivers/video/omap2/dss/sdi.c | 54 ++-- drivers/video/omap2/dss/venc.c | 78 +++-- drivers/video/omap2/dss/venc_panel.c | 53 +++- drivers/video/omap2/omapfb/omapfb-ioctl.c |4 +- drivers/video/omap2/omapfb/omapfb-main.c |7 +- drivers/video/omap2/omapfb/omapfb.h|5 +- include/video/omapdss.h| 172 ++- 35 files changed, 1350 insertions(+), 666 deletions(-) create mode 100644 drivers/video/omap2/dss/output.c -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 02/23] OMAPDSS: outputs: Create and initialize output instances
Create output instances by having an init function in the probes of the platform device drivers for different interfaces. Create a small function for each interface to initialize the output entity's fields type and id. In the probe of each interface driver, the output entities are created before the *_probe_pdata() functions intentionally. This is done to ensure that the output entity is prepared before the panels connected to the output are registered. We need the output entities to be ready because OMAPDSS will try to make connections between overlays, managers, outputs and devices during the panel's probe. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/dpi.c | 20 drivers/video/omap2/dss/dsi.c | 26 -- drivers/video/omap2/dss/hdmi.c | 18 ++ drivers/video/omap2/dss/rfbi.c | 19 +++ drivers/video/omap2/dss/sdi.c | 20 drivers/video/omap2/dss/venc.c | 20 6 files changed, 121 insertions(+), 2 deletions(-) diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index f260343..4eca2e7 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -408,10 +408,30 @@ static void __init dpi_probe_pdata(struct platform_device *pdev) } } +static int __init dpi_init_output(struct platform_device *pdev) +{ + struct omap_dss_output *out; + + out = dss_create_output(pdev); + if (!out) + return -ENOMEM; + + out-id = OMAP_DSS_OUTPUT_DPI; + out-type = OMAP_DISPLAY_TYPE_DPI; + + return 0; +} + static int __init omap_dpi_probe(struct platform_device *pdev) { + int r; + mutex_init(dpi.lock); + r = dpi_init_output(pdev); + if (r) + return r; + dpi_probe_pdata(pdev); return 0; diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 659b6cd..22e0873 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -4903,6 +4903,23 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev) } } +static int __init dsi_init_output(struct platform_device *dsidev, + struct dsi_data *dsi) +{ + struct omap_dss_output *out; + + out = dss_create_output(dsidev); + if (!out) + return -ENOMEM; + + out-id = dsi-module_id == 0 ? + OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; + + out-type = OMAP_DISPLAY_TYPE_DSI; + + return 0; +} + /* DSI1 HW IP initialisation */ static int __init omap_dsihw_probe(struct platform_device *dsidev) { @@ -4997,10 +5014,14 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev) else dsi-num_lanes_supported = 3; - dsi_probe_pdata(dsidev); - dsi_runtime_put(dsidev); + r = dsi_init_output(dsidev, dsi); + if (r) + goto err_init_output; + + dsi_probe_pdata(dsidev); + if (dsi-module_id == 0) dss_debugfs_create_file(dsi1_regs, dsi1_dump_regs); else if (dsi-module_id == 1) @@ -5014,6 +5035,7 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev) #endif return 0; +err_init_output: err_runtime_get: pm_runtime_disable(dsidev-dev); dsi_put_clocks(dsidev); diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 0cdf246..d32dbc3 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -890,6 +890,20 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev) } } +static int __init hdmi_init_output(struct platform_device *pdev) +{ + struct omap_dss_output *out; + + out = dss_create_output(pdev); + if (!out) + return -ENOMEM; + + out-id = OMAP_DSS_OUTPUT_HDMI; + out-type = OMAP_DISPLAY_TYPE_HDMI; + + return 0; +} + /* HDMI HW IP initialisation */ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) { @@ -933,6 +947,10 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) dss_debugfs_create_file(hdmi, hdmi_dump_regs); + r = hdmi_init_output(pdev); + if (r) + return r; + hdmi_probe_pdata(pdev); return 0; diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 5a9c0e9..9d9244c 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c @@ -967,6 +967,20 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev) } } +static int __init rfbi_init_output(struct platform_device *pdev) +{ + struct omap_dss_output *out; + + out = dss_create_output(pdev); + if (!out) + return -ENOMEM; + + out-id = OMAP_DSS_OUTPUT_DBI; + out-type = OMAP_DISPLAY_TYPE_DBI; + + return 0; +} + /*
[PATCH 01/23] OMAPDSS: outputs: Create a new entity called outputs
The current OMAPDSS design contains 3 software entities: Overlays, Managers and Devices. These map to pipelines, overlay managers and the panels respectively in hardware. One or more overlays connect to a manager to represent a composition, the manager connects to a device(generally a display) to display the content. The part of DSS hardware which isn't represented by any of the above entities are interfaces/outputs that connect to an overlay manager, i.e blocks like DSI, HDMI, VENC and so on. Currently, an overlay manager directly connects to the display, and the output to which it is actually connected is ignored. The panel driver of the display is responsible of calling output specific functions to configure the output. Adding outputs as a new software entity gives us the following benefits: - Have exact information on the possible connections between managers and outputs: A manager can't connect to each and every output, there only limited hardware links between a manager's video port and some of the outputs. - Remove hacks related to connecting managers and devices: Currently, default links between managers and devices are set in a not so clean way. Matching is done via comparing the device type, and the display types supported by the manager. This isn't sufficient to establish all the possible links between managers, outputs and devices in hardware. - Make panel drivers more generic: The DSS panel drivers currently call interface/output specific functions to configure the hardware IP. When making these calls, the driver isn't actually aware of the underlying output. The output driver extracts information from the panel's omap_dss_device pointer to figure out which interface it is connected to, and then configures the corresponding output block. An example of this is when a DSI panel calls dsi functions, the dsi driver figures out whether the panel is connected to DSI1 or DSI2. This isn't correct, and having output as entities will give the panel driver the exact information on which output to configure. Having outputs also gives the opportunity to make panel drivers generic across different platforms/SoCs, this is achieved as omap specific output calls can be replaced by ops of a particular output type. - Have more complex connections between managers, outputs and devices: OMAPDSS currently doesn't support use cases like 2 outputs connect to a single device. This can be achieved by extending properties of outputs to connect to more managers or devices. - Represent writeback as an output: The writeback pipeline fits well in OMAPDSS as compared to overlays, managers or devices. Add a new struct to represent outputs. An output struct holds pointers to the manager and device structs to which it is connected. Add functions which can add an output, or look for one. Create an enum which represent each output instance. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/Makefile |2 +- drivers/video/omap2/dss/core.c |1 + drivers/video/omap2/dss/dss.h|4 +++ drivers/video/omap2/dss/output.c | 58 ++ include/video/omapdss.h | 30 5 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 drivers/video/omap2/dss/output.c diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 30a48fb..645f8c3 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_OMAP2_DSS) += omapdss.o omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ - manager.o overlay.o apply.o + manager.o overlay.o output.o apply.o omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index c35a248..2eccd74 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -239,6 +239,7 @@ static int __init omap_dss_probe(struct platform_device *pdev) dss_init_overlay_managers(pdev); dss_init_overlays(pdev); + dss_init_outputs(); r = dss_initialize_debugfs(); if (r) diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 41c00dc..8a7c94c 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -222,6 +222,10 @@ int dss_ovl_set_manager(struct omap_overlay *ovl, struct omap_overlay_manager *mgr); int dss_ovl_unset_manager(struct omap_overlay *ovl); +/* output */ +struct omap_dss_output *dss_create_output(struct platform_device *pdev); +void dss_init_outputs(void); + /* display */ int dss_suspend_all_devices(void); int dss_resume_all_devices(void); diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c new file mode 100644 index 000..034ebbe
[PATCH 04/23] OMAPDSS: APPLY: Add manager set/unset output ops for omap_overlay_manager
Add set_output/unset_output ops for overlay managers, these form links between managers and outputs. Create a function in dss features which tell all the output instances that connect to a manager, use it when a manager tries to set an output. Add a constraint of not unsetting an output when the manager is enabled. Keep the omap_dss_device pointer and set/unset_device ops in overlay_manager for now to not break things. Keep the dss feature function get_supported_displays as it's used in some places. These will be removed later. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/apply.c| 70 drivers/video/omap2/dss/dss.h |3 ++ drivers/video/omap2/dss/dss_features.c | 52 drivers/video/omap2/dss/dss_features.h |1 + drivers/video/omap2/dss/manager.c |4 ++ include/video/omapdss.h|5 +++ 6 files changed, 135 insertions(+) diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 74f1a58..d241407 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -1311,6 +1311,76 @@ err: return r; } +int dss_mgr_set_output(struct omap_overlay_manager *mgr, + struct omap_dss_output *output) +{ + int r; + + mutex_lock(apply_lock); + + if (mgr-output) { + DSSERR(manager %s is already connected to an output\n, + mgr-name); + r = -EINVAL; + goto err; + } + + if ((mgr-supported_outputs output-id) == 0) { + DSSERR(output does not support manager %s\n, + mgr-name); + r = -EINVAL; + goto err; + } + + output-manager = mgr; + mgr-output = output; + + mutex_unlock(apply_lock); + + return 0; +err: + mutex_unlock(apply_lock); + return r; +} + +int dss_mgr_unset_output(struct omap_overlay_manager *mgr) +{ + int r; + struct mgr_priv_data *mp = get_mgr_priv(mgr); + unsigned long flags; + + mutex_lock(apply_lock); + + if (!mgr-output) { + DSSERR(failed to unset output, output not set\n); + r = -EINVAL; + goto err; + } + + spin_lock_irqsave(data_lock, flags); + + if (mp-enabled) { + DSSERR(output can't be unset when manager is enabled\n); + r = -EINVAL; + goto err1; + } + + spin_unlock_irqrestore(data_lock, flags); + + mgr-output-manager = NULL; + mgr-output = NULL; + + mutex_unlock(apply_lock); + + return 0; +err1: + spin_unlock_irqrestore(data_lock, flags); +err: + mutex_unlock(apply_lock); + + return r; +} + static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr, const struct omap_video_timings *timings) { diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 8a7c94c..a119506 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -205,6 +205,9 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr, int dss_mgr_set_device(struct omap_overlay_manager *mgr, struct omap_dss_device *dssdev); int dss_mgr_unset_device(struct omap_overlay_manager *mgr); +int dss_mgr_set_output(struct omap_overlay_manager *mgr, + struct omap_dss_output *output); +int dss_mgr_unset_output(struct omap_overlay_manager *mgr); void dss_mgr_set_timings(struct omap_overlay_manager *mgr, const struct omap_video_timings *timings); void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 9387097..43f8491 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -47,6 +47,7 @@ struct omap_dss_features { const int num_mgrs; const int num_ovls; const enum omap_display_type *supported_displays; + const enum omap_dss_output_id *supported_outputs; const enum omap_color_mode *supported_color_modes; const enum omap_overlay_caps *overlay_caps; const char * const *clksrc_names; @@ -144,6 +145,46 @@ static const enum omap_display_type omap4_dss_supported_displays[] = { OMAP_DISPLAY_TYPE_DSI, }; +static const enum omap_dss_output_id omap2_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DSS_OUTPUT_VENC, +}; + +static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = { + /* OMAP_DSS_CHANNEL_LCD */ + OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | + OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1, + + /* OMAP_DSS_CHANNEL_DIGIT */ + OMAP_DSS_OUTPUT_VENC, +}; + +static const enum
[PATCH 03/23] OMAPDSS: output: Add set/unset device ops for omap_dss_output
An output entity represented by the struct omap_dss_output connects to a omap_dss_device entity. Add functions to set or unset an output's device. This is similar to how managers and devices were connected previously. An output can connect to a device without being connected to a manager. However, the output needs to eventually connect to a manager so that the connected panel can be enabled. Keep the omap_overlay_manager pointer in omap_dss_device for now to prevent breaking things. This will be removed later when outputs are supported completely. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/output.c | 67 ++ include/video/omapdss.h |5 +++ 2 files changed, 72 insertions(+) diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c index 034ebbe..ac57b19 100644 --- a/drivers/video/omap2/dss/output.c +++ b/drivers/video/omap2/dss/output.c @@ -24,6 +24,70 @@ #include dss.h static struct list_head output_list; +static DEFINE_MUTEX(output_lock); + +static int dss_output_set_device(struct omap_dss_output *out, + struct omap_dss_device *dssdev) +{ + int r; + + mutex_lock(output_lock); + + if (out-device) { + DSSERR(output already has device %s connected to it\n, + out-device-name); + r = -EINVAL; + goto err; + } + + if (out-type != dssdev-type) { + DSSERR(output type and display type don't match\n); + r = -EINVAL; + goto err; + } + + out-device = dssdev; + dssdev-output = out; + + mutex_unlock(output_lock); + + return 0; +err: + mutex_unlock(output_lock); + + return r; +} + +static int dss_output_unset_device(struct omap_dss_output *out) +{ + int r; + + mutex_lock(output_lock); + + if (!out-device) { + DSSERR(output doesn't have a device connected to it\n); + r = -EINVAL; + goto err; + } + + if (out-device-state != OMAP_DSS_DISPLAY_DISABLED) { + DSSERR(device %s is not disabled, cannot unset device\n, + out-device-name); + r = -EINVAL; + goto err; + } + + out-device-output = NULL; + out-device = NULL; + + mutex_unlock(output_lock); + + return 0; +err: + mutex_unlock(output_lock); + + return r; +} struct omap_dss_output *dss_create_output(struct platform_device *pdev) { @@ -35,6 +99,9 @@ struct omap_dss_output *dss_create_output(struct platform_device *pdev) out-pdev = pdev; + out-set_device = dss_output_set_device; + out-unset_device = dss_output_unset_device; + list_add_tail(out-list, output_list); return out; diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 0ba613f..2e40f27 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -518,6 +518,10 @@ struct omap_dss_output { struct omap_overlay_manager *manager; struct omap_dss_device *device; + + int (*set_device) (struct omap_dss_output *out, + struct omap_dss_device *dssdev); + int (*unset_device) (struct omap_dss_output *out); }; struct omap_dss_device { @@ -619,6 +623,7 @@ struct omap_dss_device { enum omap_display_caps caps; struct omap_overlay_manager *manager; + struct omap_dss_output *output; enum omap_dss_display_state state; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 06/23] OMAP_VOUT: Remove manager-device references
With the introduction of output entities, managers will now connect to outputs. Use the helper op for managers named get_device. This will abstract away the information on how to get the device from an overlay manager. Using the helper function will reduce the number of pointer dereferences a user of OMAPDSS needs to do and reduce risk of a NULL dereference. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/media/video/omap/omap_vout.c | 81 -- 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index 88cf9d9..0ebf87e 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -454,11 +454,16 @@ static int omapvid_init(struct omap_vout_device *vout, u32 addr) win = vout-win; for (i = 0; i ovid-num_overlays; i++) { + struct omap_dss_device *dssdev; + ovl = ovid-overlays[i]; - if (!ovl-manager || !ovl-manager-device) + dssdev = ovl-manager ? + ovl-manager-get_device(ovl-manager) : NULL; + + if (!dssdev) return -EINVAL; - timing = ovl-manager-device-panel.timings; + timing = dssdev-panel.timings; outw = win-w.width; outh = win-w.height; @@ -515,8 +520,12 @@ static int omapvid_apply_changes(struct omap_vout_device *vout) struct omapvideo_info *ovid = vout-vid_info; for (i = 0; i ovid-num_overlays; i++) { + struct omap_dss_device *dssdev; + ovl = ovid-overlays[i]; - if (!ovl-manager || !ovl-manager-device) + dssdev = ovl-manager ? + ovl-manager-get_device(ovl-manager) : NULL; + if (!dssdev) return -EINVAL; ovl-manager-apply(ovl-manager); } @@ -579,12 +588,15 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus) ovid = vout-vid_info; ovl = ovid-overlays[0]; - /* get the display device attached to the overlay */ - if (!ovl-manager || !ovl-manager-device) - return; mgr_id = ovl-manager-id; - cur_display = ovl-manager-device; + + /* get the display device attached to the overlay */ + cur_display = ovl-manager ? + ovl-manager-get_device(ovl-manager) : NULL; + + if (!cur_display) + return; spin_lock(vout-vbq_lock); do_gettimeofday(timevalue); @@ -948,7 +960,10 @@ static int omap_vout_release(struct file *file) /* Disable all the overlay managers connected with this interface */ for (i = 0; i ovid-num_overlays; i++) { struct omap_overlay *ovl = ovid-overlays[i]; - if (ovl-manager ovl-manager-device) + struct omap_dss_device *dssdev = ovl-manager ? + ovl-manager-get_device(ovl-manager) : NULL; + + if (dssdev) ovl-disable(ovl); } /* Turn off the pipeline */ @@ -1081,14 +1096,17 @@ static int vidioc_try_fmt_vid_out(struct file *file, void *fh, struct omapvideo_info *ovid; struct omap_video_timings *timing; struct omap_vout_device *vout = fh; + struct omap_dss_device *dssdev; ovid = vout-vid_info; ovl = ovid-overlays[0]; + /* get the display device attached to the overlay */ + dssdev = ovl-manager ? ovl-manager-get_device(ovl-manager) : NULL; - if (!ovl-manager || !ovl-manager-device) + if (!dssdev) return -EINVAL; - /* get the display device attached to the overlay */ - timing = ovl-manager-device-panel.timings; + + timing = dssdev-panel.timings; vout-fbuf.fmt.height = timing-y_res; vout-fbuf.fmt.width = timing-x_res; @@ -1105,6 +1123,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, struct omapvideo_info *ovid; struct omap_video_timings *timing; struct omap_vout_device *vout = fh; + struct omap_dss_device *dssdev; if (vout-streaming) return -EBUSY; @@ -1113,13 +1132,14 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, ovid = vout-vid_info; ovl = ovid-overlays[0]; + dssdev = ovl-manager ? ovl-manager-get_device(ovl-manager) : NULL; /* get the display device attached to the overlay */ - if (!ovl-manager || !ovl-manager-device) { + if (!dssdev) { ret = -EINVAL; goto s_fmt_vid_out_exit; } - timing = ovl-manager-device-panel.timings; + timing = dssdev-panel.timings; /* We dont support RGB24-packed mode if vrfb rotation * is enabled*/ @@ -1298,6 +1318,7 @@ static int vidioc_s_crop(struct file *file, void *fh,
[PATCH 05/23] OMAPDSS: Remove manager-device references
With the introduction of output entities, managers will now connect to outputs. Create a helper op for managers named get_device. This will abstract away the information on how to get the device from an overlay manager. The get_device op currently retrieves the output via a manager-device reference. This will be later replaced by a manager-output-device reference. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/apply.c |6 -- drivers/video/omap2/dss/dispc.c | 10 +++--- drivers/video/omap2/dss/manager.c | 19 ++- include/video/omapdss.h |2 ++ 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index d241407..8a05cbc 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -1607,7 +1607,8 @@ int dss_ovl_enable(struct omap_overlay *ovl) goto err1; } - if (ovl-manager == NULL || ovl-manager-device == NULL) { + if (ovl-manager == NULL || + ovl-manager-get_device(ovl-manager) == NULL) { r = -EINVAL; goto err1; } @@ -1676,7 +1677,8 @@ int dss_ovl_disable(struct omap_overlay *ovl) goto err; } - if (ovl-manager == NULL || ovl-manager-device == NULL) { + if (ovl-manager == NULL || + ovl-manager-get_device(ovl-manager) == NULL) { r = -EINVAL; goto err; } diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index ff52702..33061f5 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -3503,7 +3503,7 @@ static void dispc_error_worker(struct work_struct *work) bit = mgr_desc[i].sync_lost_irq; if (bit errors) { - struct omap_dss_device *dssdev = mgr-device; + struct omap_dss_device *dssdev = mgr-get_device(mgr); bool enable; DSSERR(SYNC_LOST on channel %s, restarting the output @@ -3534,9 +3534,13 @@ static void dispc_error_worker(struct work_struct *work) DSSERR(OCP_ERR\n); for (i = 0; i omap_dss_get_num_overlay_managers(); ++i) { struct omap_overlay_manager *mgr; + struct omap_dss_device *dssdev; + mgr = omap_dss_get_overlay_manager(i); - if (mgr-device mgr-device-driver) - mgr-device-driver-disable(mgr-device); + dssdev = mgr-get_device(mgr); + + if (dssdev dssdev-driver) + dssdev-driver-disable(dssdev); } } diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index e15fa5f..fd39f66 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -43,8 +43,10 @@ static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf) { - return snprintf(buf, PAGE_SIZE, %s\n, - mgr-device ? mgr-device-name : none); + struct omap_dss_device *dssdev = mgr-get_device(mgr); + + return snprintf(buf, PAGE_SIZE, %s\n, dssdev ? + dssdev-name : none); } static ssize_t manager_display_store(struct omap_overlay_manager *mgr, @@ -72,7 +74,7 @@ static ssize_t manager_display_store(struct omap_overlay_manager *mgr, if (dssdev) DSSDBG(display %s found\n, dssdev-name); - if (mgr-device) { + if (mgr-get_device(mgr)) { r = mgr-unset_device(mgr); if (r) { DSSERR(failed to unset display\n); @@ -490,9 +492,15 @@ static struct kobj_type manager_ktype = { .default_attrs = manager_sysfs_attrs, }; +static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr) +{ + return mgr-device; +} + static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) { unsigned long timeout = msecs_to_jiffies(500); + struct omap_dss_device *dssdev = mgr-get_device(mgr); u32 irq; int r; @@ -500,9 +508,9 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) if (r) return r; - if (mgr-device-type == OMAP_DISPLAY_TYPE_VENC) + if (dssdev-type == OMAP_DISPLAY_TYPE_VENC) irq = DISPC_IRQ_EVSYNC_ODD; - else if (mgr-device-type == OMAP_DISPLAY_TYPE_HDMI) + else if (dssdev-type == OMAP_DISPLAY_TYPE_HDMI) irq = DISPC_IRQ_EVSYNC_EVEN; else irq = dispc_mgr_get_vsync_irq(mgr-id); @@ -556,6 +564,7 @@ int dss_init_overlay_managers(struct platform_device
[PATCH 07/23] OMAPFB: remove manager-device references
With the introduction of output entities, managers will now connect to outputs. Use the helper op for managers named get_device. This will abstract away the information on how to get the device from an overlay manager. Using the helper function will reduce the number of pointer dereferences a user of OMAPDSS needs to do and reduce risk of a NULL dereference. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/omapfb/omapfb-main.c |7 +-- drivers/video/omap2/omapfb/omapfb.h |5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index fc671d3..c6992be 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -2353,6 +2353,7 @@ static int __init omapfb_probe(struct platform_device *pdev) struct omap_overlay *ovl; struct omap_dss_device *def_display; struct omap_dss_device *dssdev; + struct omap_dss_device *mgr_device; DBG(omapfb_probe\n); @@ -2426,8 +2427,10 @@ static int __init omapfb_probe(struct platform_device *pdev) /* gfx overlay should be the default one. find a display * connected to that, and use it as default display */ ovl = omap_dss_get_overlay(0); - if (ovl-manager ovl-manager-device) { - def_display = ovl-manager-device; + mgr_device = ovl-manager ? + ovl-manager-get_device(ovl-manager) : NULL; + if (mgr_device) { + def_display = mgr_device; } else { dev_warn(pdev-dev, cannot find default display\n); def_display = NULL; diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h index 30361a0..2782b1f 100644 --- a/drivers/video/omap2/omapfb/omapfb.h +++ b/drivers/video/omap2/omapfb/omapfb.h @@ -148,8 +148,9 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi) /* XXX: returns the display connected to first attached overlay */ for (i = 0; i ofbi-num_overlays; i++) { - if (ofbi-overlays[i]-manager) - return ofbi-overlays[i]-manager-device; + struct omap_overlay_manager *mgr = ofbi-overlays[i]-manager; + if (mgr) + return mgr-get_device(mgr); } return NULL; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 08/23] OMAPDRM: Remove manager-device references
With the introduction of output entities, managers will now connect to outputs. Use the helper op for managers named get_device. This will abstract away the information on how to get the device from an overlay manager. Using the helper function will reduce the number of pointer dereferences a user of OMAPDSS needs to do and reduce risk of a NULL dereference. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/staging/omapdrm/omap_drv.c |5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index 4beab94..64a354a 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c @@ -106,7 +106,8 @@ static void dump_video_chains(void) for (i = 0; i omap_dss_get_num_overlays(); i++) { struct omap_overlay *ovl = omap_dss_get_overlay(i); struct omap_overlay_manager *mgr = ovl-manager; - struct omap_dss_device *dssdev = mgr ? mgr-device : NULL; + struct omap_dss_device *dssdev = mgr ? + mgr-get_device(mgr) : NULL; if (dssdev) { DBG(%d: %s - %s - %s, i, ovl-name, mgr-name, dssdev-name); @@ -185,7 +186,7 @@ static int create_connector(struct drm_device *dev, for (j = 0; j priv-num_encoders; j++) { struct omap_overlay_manager *mgr = omap_encoder_get_manager(priv-encoders[j]); - if (mgr-device == dssdev) { + if (mgr-get_device(mgr) == dssdev) { drm_mode_connector_attach_encoder(connector, priv-encoders[j]); } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/23] OMAPDSS: Create links between managers, outputs and devices
Links between DSS entities are made in dss_recheck_connections when a new panel is probed. Rewrite the code in dss_recheck_connections to link managers to outputs, and outputs to devices. The fields in omap_dss_device struct gives information on which output and manager to connect to. The desired manager and output pointers are retrieved and prepared(existing outputs/devices unset, if default display)) to form the desired links. The output is linked to the device, and then the manager to the output. If a probed device's required manager isn't free, the required output is still connected to the device so that it's easier to use the panel in the future. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/overlay.c | 96 + 1 file changed, 56 insertions(+), 40 deletions(-) diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 952c6fa..07605f1 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c @@ -525,51 +525,67 @@ void dss_init_overlays(struct platform_device *pdev) void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) { int i; - struct omap_overlay_manager *lcd_mgr; - struct omap_overlay_manager *tv_mgr; - struct omap_overlay_manager *lcd2_mgr = NULL; - struct omap_overlay_manager *lcd3_mgr = NULL; struct omap_overlay_manager *mgr = NULL; + struct omap_dss_output *out = NULL; + enum omap_dss_output_id id; + + switch (dssdev-type) { + case OMAP_DISPLAY_TYPE_DPI: + out = omap_dss_get_output(OMAP_DSS_OUTPUT_DPI); + break; + case OMAP_DISPLAY_TYPE_DBI: + out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI); + break; + case OMAP_DISPLAY_TYPE_SDI: + out = omap_dss_get_output(OMAP_DSS_OUTPUT_SDI); + break; + case OMAP_DISPLAY_TYPE_VENC: + out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC); + break; + case OMAP_DISPLAY_TYPE_HDMI: + out = omap_dss_get_output(OMAP_DSS_OUTPUT_HDMI); + break; + case OMAP_DISPLAY_TYPE_DSI: + id = dssdev-phy.dsi.module == 0 ? OMAP_DSS_OUTPUT_DSI1 : + OMAP_DSS_OUTPUT_DSI2; + out = omap_dss_get_output(id); + break; + default: + break; + } - lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD); - tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_DIGIT); - if (dss_has_feature(FEAT_MGR_LCD3)) - lcd3_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD3); - if (dss_has_feature(FEAT_MGR_LCD2)) - lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD2); - - if (dssdev-channel == OMAP_DSS_CHANNEL_LCD3) { - if (!lcd3_mgr-device || force) { - if (lcd3_mgr-device) - lcd3_mgr-unset_device(lcd3_mgr); - lcd3_mgr-set_device(lcd3_mgr, dssdev); - mgr = lcd3_mgr; - } - } else if (dssdev-channel == OMAP_DSS_CHANNEL_LCD2) { - if (!lcd2_mgr-device || force) { - if (lcd2_mgr-device) - lcd2_mgr-unset_device(lcd2_mgr); - lcd2_mgr-set_device(lcd2_mgr, dssdev); - mgr = lcd2_mgr; - } - } else if (dssdev-type != OMAP_DISPLAY_TYPE_VENC -dssdev-type != OMAP_DISPLAY_TYPE_HDMI) { - if (!lcd_mgr-device || force) { - if (lcd_mgr-device) - lcd_mgr-unset_device(lcd_mgr); - lcd_mgr-set_device(lcd_mgr, dssdev); - mgr = lcd_mgr; - } + /* +* We don't want to touch board files and mention channel for VENC +* devices. Force the channel as DIGIT for HDMI and VENC devices +*/ + if (dssdev-type == OMAP_DISPLAY_TYPE_VENC || + dssdev-type == OMAP_DISPLAY_TYPE_HDMI) + dssdev-channel = OMAP_DSS_CHANNEL_DIGIT; + + mgr = omap_dss_get_overlay_manager(dssdev-channel); + + if (!mgr || !out) { + DSSERR(Incorrect manager or output\n); + return; } - if (dssdev-type == OMAP_DISPLAY_TYPE_VENC - || dssdev-type == OMAP_DISPLAY_TYPE_HDMI) { - if (!tv_mgr-device || force) { - if (tv_mgr-device) - tv_mgr-unset_device(tv_mgr); - tv_mgr-set_device(tv_mgr, dssdev); - mgr = tv_mgr; + if (!mgr-output || force) { + struct omap_dss_output *curr_out = mgr-output; + + if (curr_out) { + if
[PATCH 10/23] OMAPDSS: DPI: Pass outputs from panel driver to DPI interface driver
With outputs introduces as new entities, we can now pass output pointer to functions used to configure the connected interface. These functions currently pass the omap_dss_device pointer, and extract output information via omap_dss_device. This is unnecessary, and it doesn't make sense for interface related functions to get the panel's/device's pointer, it should receive a pointer related to the connected interface, which in our case is the output entity. With the addition of outputs. There is a possibility that an omap_dss_device isn't connected to an output yet. Ensure that panel drivers call the interface functions only if outputs are non NULL. Modify DPI functions to pass omap_dss_output pointer instead of omap_dss_device pointer. Modify the panel drivers to call the updated functions. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/displays/panel-generic-dpi.c | 27 ++--- .../omap2/displays/panel-lgphilips-lb035q02.c | 16 +++-- .../omap2/displays/panel-nec-nl8048hl11-01b.c | 15 +++-- drivers/video/omap2/displays/panel-picodlp.c | 15 +++-- .../video/omap2/displays/panel-sharp-ls037v7dw01.c | 16 +++-- drivers/video/omap2/displays/panel-tfp410.c| 17 -- .../video/omap2/displays/panel-tpo-td043mtea1.c| 29 ++--- drivers/video/omap2/dss/dpi.c | 64 ++-- include/video/omapdss.h| 12 ++-- 9 files changed, 133 insertions(+), 78 deletions(-) diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 88295c5..76ee8df 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c @@ -561,14 +561,18 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev) struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); struct panel_drv_data *drv_data = dev_get_drvdata(dssdev-dev); struct panel_config *panel_config = drv_data-panel_config; + struct omap_dss_output *out = dssdev-output; + + if (out == NULL) + return -ENODEV; if (dssdev-state == OMAP_DSS_DISPLAY_ACTIVE) return 0; - omapdss_dpi_set_timings(dssdev, dssdev-panel.timings); - omapdss_dpi_set_data_lines(dssdev, dssdev-phy.dpi.data_lines); + omapdss_dpi_set_timings(out, dssdev-panel.timings); + omapdss_dpi_set_data_lines(out, dssdev-phy.dpi.data_lines); - r = omapdss_dpi_display_enable(dssdev); + r = omapdss_dpi_display_enable(out); if (r) goto err0; @@ -584,7 +588,7 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev) return 0; err1: - omapdss_dpi_display_disable(dssdev); + omapdss_dpi_display_disable(out); err0: return r; } @@ -594,6 +598,7 @@ static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev) struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); struct panel_drv_data *drv_data = dev_get_drvdata(dssdev-dev); struct panel_config *panel_config = drv_data-panel_config; + struct omap_dss_output *out = dssdev-output; if (dssdev-state != OMAP_DSS_DISPLAY_ACTIVE) return; @@ -605,7 +610,7 @@ static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev) if (panel_config-power_off_delay) msleep(panel_config-power_off_delay); - omapdss_dpi_display_disable(dssdev); + omapdss_dpi_display_disable(out); } static int generic_dpi_panel_probe(struct omap_dss_device *dssdev) @@ -726,10 +731,14 @@ static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { struct panel_drv_data *drv_data = dev_get_drvdata(dssdev-dev); + struct omap_dss_output *out = dssdev-output; + + if (out == NULL) + return; mutex_lock(drv_data-lock); - omapdss_dpi_set_timings(dssdev, timings); + omapdss_dpi_set_timings(out, timings); dssdev-panel.timings = *timings; @@ -752,11 +761,15 @@ static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { struct panel_drv_data *drv_data = dev_get_drvdata(dssdev-dev); + struct omap_dss_output *out = dssdev-output; int r; + if (out == NULL) + return -ENODEV; + mutex_lock(drv_data-lock); - r = dpi_check_timings(dssdev, timings); + r = dpi_check_timings(out, timings); mutex_unlock(drv_data-lock); diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c index 90c1cab..2764c32 100644 --- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c +++
[PATCH 11/23] OMAPDSS: DSI: Remove dsi_pdev_map global struct
dsi_pdev_map is a struct visible globally in the DSI driver to get the platform device pointer of the DSI device corresponding to it's module ID. This was required because there was no clean way to derive the platform device from the DSI module instance number or from the connected panel. With the new output entity, it is possible to retrieve the platform device pointer if the omap_dss_output pointer is available. Modify the functions dsi_get_dsidev_from_dssdev() dsi_get_dsidev_from_id() so that they use output instead of dsi_pdev_map to retrieve the dsi platform device pointer. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/dsi.c | 14 +- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 22e0873..19a4d4d 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -344,8 +344,6 @@ struct dsi_packet_sent_handler_data { struct completion *completion; }; -static struct platform_device *dsi_pdev_map[MAX_NUM_DSI]; - #ifdef DEBUG static bool dsi_perf; module_param(dsi_perf, bool, 0644); @@ -358,12 +356,19 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev) { - return dsi_pdev_map[dssdev-phy.dsi.module]; + return dssdev-output-pdev; } struct platform_device *dsi_get_dsidev_from_id(int module) { - return dsi_pdev_map[module]; + struct omap_dss_output *out; + enum omap_dss_output_id id; + + id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; + + out = omap_dss_get_output(id); + + return out-pdev; } static inline void dsi_write_reg(struct platform_device *dsidev, @@ -4934,7 +4939,6 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev) dsi-module_id = dsidev-id; dsi-pdev = dsidev; - dsi_pdev_map[dsi-module_id] = dsidev; dev_set_drvdata(dsidev-dev, dsi); spin_lock_init(dsi-irq_lock); -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 13/23] OMAPDSS: SDI: Pass outputs from panel driver to SDI interface driver
With outputs introduces as new entities, we can now pass output pointer to functions used to configure the connected interface. These functions currently pass the omap_dss_device pointer, and extract output information via omap_dss_device. This is unnecessary, and it doesn't make sense for interface related functions to get the panel's/device's pointer, it should receive a pointer related to the connected interface, which in our case is the output entity. With the addition of outputs. There is a possibility that an omap_dss_device isn't connected to an output yet. Ensure that panel drivers call the interface functions only if outputs are non NULL. Modify SDI functions to pass omap_dss_output pointer instead of omap_dss_device pointer. Modify the panel drivers to call the updated functions. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/displays/panel-acx565akm.c | 22 ++- drivers/video/omap2/dss/sdi.c | 34 include/video/omapdss.h|8 +++--- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c index c835aa7..c517b29 100644 --- a/drivers/video/omap2/displays/panel-acx565akm.c +++ b/drivers/video/omap2/displays/panel-acx565akm.c @@ -591,19 +591,23 @@ static void acx_panel_remove(struct omap_dss_device *dssdev) static int acx_panel_power_on(struct omap_dss_device *dssdev) { struct acx565akm_device *md = acx_dev; + struct omap_dss_output *out = dssdev-output; int r; dev_dbg(dssdev-dev, %s\n, __func__); + if (out == NULL) + return -ENODEV; + if (dssdev-state == OMAP_DSS_DISPLAY_ACTIVE) return 0; mutex_lock(md-mutex); - omapdss_sdi_set_timings(dssdev, dssdev-panel.timings); - omapdss_sdi_set_datapairs(dssdev, dssdev-phy.sdi.datapairs); + omapdss_sdi_set_timings(out, dssdev-panel.timings); + omapdss_sdi_set_datapairs(out, dssdev-phy.sdi.datapairs); - r = omapdss_sdi_display_enable(dssdev); + r = omapdss_sdi_display_enable(out); if (r) { pr_err(%s sdi enable failed\n, __func__); goto fail_unlock; @@ -646,7 +650,7 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev) return acx565akm_bl_update_status(md-bl_dev); fail: - omapdss_sdi_display_disable(dssdev); + omapdss_sdi_display_disable(out); fail_unlock: mutex_unlock(md-mutex); return r; @@ -655,6 +659,7 @@ fail_unlock: static void acx_panel_power_off(struct omap_dss_device *dssdev) { struct acx565akm_device *md = acx_dev; + struct omap_dss_output *out = dssdev-output; dev_dbg(dssdev-dev, %s\n, __func__); @@ -684,7 +689,7 @@ static void acx_panel_power_off(struct omap_dss_device *dssdev) /* FIXME need to tweak this delay */ msleep(100); - omapdss_sdi_display_disable(dssdev); + omapdss_sdi_display_disable(out); mutex_unlock(md-mutex); } @@ -734,7 +739,12 @@ static int acx_panel_resume(struct omap_dss_device *dssdev) static void acx_panel_set_timings(struct omap_dss_device *dssdev, struct omap_video_timings *timings) { - omapdss_sdi_set_timings(dssdev, timings); + struct omap_dss_output *out = dssdev-output; + + if (out == NULL) + return; + + omapdss_sdi_set_timings(out, timings); dssdev-panel.timings = *timings; } diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index a5632d0..4f669be 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -38,7 +38,7 @@ static struct { int datapairs; } sdi; -static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) +static void sdi_config_lcd_manager(struct omap_dss_output *out) { sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; @@ -48,10 +48,10 @@ static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) sdi.mgr_config.video_port_width = 24; sdi.mgr_config.lcden_sig_polarity = 1; - dss_mgr_set_lcd_config(dssdev-manager, sdi.mgr_config); + dss_mgr_set_lcd_config(out-manager, sdi.mgr_config); } -int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) +int omapdss_sdi_display_enable(struct omap_dss_output *out) { struct omap_video_timings *t = sdi.timings; struct dss_clock_info dss_cinfo; @@ -59,12 +59,12 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) unsigned long pck; int r; - if (dssdev-manager == NULL) { + if (out-manager == NULL) { DSSERR(failed to enable display: no manager\n); return -ENODEV; } - r = omap_dss_start_device(dssdev); + r = omap_dss_start_device(out-device); if (r) {
[PATCH 14/23] OMAPDSS: RFBI: Pass outputs from panel driver to RFBI interface driver
With outputs introduces as new entities, we can now pass output pointer to functions used to configure the connected interface. These functions currently pass the omap_dss_device pointer, and extract output information via omap_dss_device. This is unnecessary, and it doesn't make sense for interface related functions to get the panel's/device's pointer, it should receive a pointer related to the connected interface, which in our case is the output entity. With the addition of outputs. There is a possibility that an omap_dss_device isn't connected to an output yet. Ensure that panel drivers call the interface functions only if outputs are non NULL. Modify DSI functions to pass omap_dss_output pointer instead of omap_dss_device pointer. Modify the panel drivers to call the updated functions. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/displays/panel-n8x0.c | 38 +-- drivers/video/omap2/dss/rfbi.c| 40 +++-- include/video/omapdss.h | 16 ++-- 3 files changed, 53 insertions(+), 41 deletions(-) diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c index 17ae85e..3601c59 100644 --- a/drivers/video/omap2/displays/panel-n8x0.c +++ b/drivers/video/omap2/displays/panel-n8x0.c @@ -116,6 +116,7 @@ static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev, int x, int y, int w, int h) { struct panel_drv_data *ddata = get_drv_data(dssdev); + struct omap_dss_output *out = dssdev-output; u8 tmp[18]; int x_end, y_end; @@ -150,17 +151,17 @@ static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev, BLIZZARD_SRC_WRITE_LCD : BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE; - omapdss_rfbi_set_pixel_size(dssdev, 16); - omapdss_rfbi_set_data_lines(dssdev, 8); + omapdss_rfbi_set_pixel_size(out, 16); + omapdss_rfbi_set_data_lines(out, 8); - omap_rfbi_configure(dssdev); + omap_rfbi_configure(out); blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18); - omapdss_rfbi_set_pixel_size(dssdev, 16); - omapdss_rfbi_set_data_lines(dssdev, 16); + omapdss_rfbi_set_pixel_size(out, 16); + omapdss_rfbi_set_data_lines(out, 16); - omap_rfbi_configure(dssdev); + omap_rfbi_configure(out); } static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf, @@ -288,10 +289,14 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev) struct panel_n8x0_data *bdata = get_board_data(dssdev); struct panel_drv_data *ddata = get_drv_data(dssdev); struct spi_device *spi = ddata-spidev; + struct omap_dss_output *out = dssdev-output; u8 rev, conf; u8 display_id[3]; const char *panel_name; + if (out == NULL) + return -ENODEV; + if (dssdev-state == OMAP_DSS_DISPLAY_ACTIVE) return 0; @@ -303,13 +308,13 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev) goto err_plat_en; } - omapdss_rfbi_set_size(dssdev, dssdev-panel.timings.x_res, + omapdss_rfbi_set_size(out, dssdev-panel.timings.x_res, dssdev-panel.timings.y_res); - omapdss_rfbi_set_pixel_size(dssdev, dssdev-ctrl.pixel_size); - omapdss_rfbi_set_data_lines(dssdev, dssdev-phy.rfbi.data_lines); - omapdss_rfbi_set_interface_timings(dssdev, dssdev-ctrl.rfbi_timings); + omapdss_rfbi_set_pixel_size(out, dssdev-ctrl.pixel_size); + omapdss_rfbi_set_data_lines(out, dssdev-phy.rfbi.data_lines); + omapdss_rfbi_set_interface_timings(out, dssdev-ctrl.rfbi_timings); - r = omapdss_rfbi_display_enable(dssdev); + r = omapdss_rfbi_display_enable(out); if (r) goto err_rfbi_en; @@ -373,7 +378,7 @@ err_inv_panel: */ /* gpio_direction_output(bdata-panel_reset, 0); */ err_inv_chip: - omapdss_rfbi_display_disable(dssdev); + omapdss_rfbi_display_disable(out); err_rfbi_en: if (bdata-platform_disable) bdata-platform_disable(dssdev); @@ -386,6 +391,7 @@ static void n8x0_panel_power_off(struct omap_dss_device *dssdev) { struct panel_n8x0_data *bdata = get_board_data(dssdev); struct panel_drv_data *ddata = get_drv_data(dssdev); + struct omap_dss_output *out = dssdev-output; struct spi_device *spi = ddata-spidev; if (dssdev-state != OMAP_DSS_DISPLAY_ACTIVE) @@ -404,7 +410,7 @@ static void n8x0_panel_power_off(struct omap_dss_device *dssdev) */ /* gpio_direction_output(bdata-panel_reset, 0); */ gpio_direction_output(bdata-ctrl_pwrdown, 0); - omapdss_rfbi_display_disable(dssdev); + omapdss_rfbi_display_disable(out); } static const struct rfbi_timings n8x0_panel_timings = { @@
Re: [RFC] ASoC: snd_soc_jack for HDMI audio: does it make sense?
On Mon, 2012-08-20 at 20:47 -0500, Ricardo Neri wrote: Hello! I have been working on prototypes for the ASoC OMAP HDMI audio driver to propagate events from the HDMI output (e.g., display getting enabled/disabled/suspended). This for the users of the driver to react to such events. For instance, if the display is disabled or disconected, audio could be stopped, rerouted or whatever other decision the user makes. This is needed because, if, for instance, the HDMI IP goes off, audio will stall and the audio users will only see a playback write error (DMA or IRQ trouble?) In my prototypes I have used snd_soc_jack for this purpose and I have some questions: *I see snd_soc_jack is used mostly for headsets and microphones with actual external mechanical connections. Strictly, in my case I propagate events originated by the OMAP display driver (changes in the power state), and not from external events. Some of these events are generated from an actual HDMI cable connection/disconnection, though. *Maybe the event should be propagated by omapdss/omapdrm/drm and the entity in charge of the audio policy should listen those events instead. *I do see SND_JACK_VIDEOOUT and SND_JACK_AVOUT types so maybe it is feasible for an audio driver to report events from an AV output. I was wondering about how much sense does it make to you guys use a snd_soc_jack in this case? How does DRM handle audio? I made a quick grep, but I see the drm drivers only enabling the audio in the HW, nothing else. If there's a common generic way to handle this, we should obviously use that. But if we need to choose between doing something custom or doing it in omapdrm driver, I think we should go for drm the only solution and forget about audio with omapfb. Tomi signature.asc Description: This is a digitally signed message part
[PATCH 16/23] OMAPDSS: VENC: Pass outputs from panel driver to VENC interface driver
With outputs introduces as new entities, we can now pass output pointer to functions used to configure the connected interface. These functions currently pass the omap_dss_device pointer, and extract output information via omap_dss_device. This is unnecessary, and it doesn't make sense for interface related functions to get the panel's/device's pointer, it should receive a pointer related to the connected interface, which in our case is the output entity. With the addition of outputs. There is a possibility that an omap_dss_device isn't connected to an output yet. Ensure that the venc panel driver calls the interface functions only if output is non NULL. Modify VENC functions to pass omap_dss_output pointer instead of omap_dss_device pointer. Modify the venc panel driver to call the updated functions. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/dss.h| 16 +- drivers/video/omap2/dss/venc.c | 58 +- drivers/video/omap2/dss/venc_panel.c | 53 --- 3 files changed, 78 insertions(+), 49 deletions(-) diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index a119506..5fd3cc5 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -476,17 +476,17 @@ static inline unsigned long venc_get_pixel_clock(void) return 0; } #endif -int omapdss_venc_display_enable(struct omap_dss_device *dssdev); -void omapdss_venc_display_disable(struct omap_dss_device *dssdev); -void omapdss_venc_set_timings(struct omap_dss_device *dssdev, +int omapdss_venc_display_enable(struct omap_dss_output *out); +void omapdss_venc_display_disable(struct omap_dss_output *out); +void omapdss_venc_set_timings(struct omap_dss_output *out, struct omap_video_timings *timings); -int omapdss_venc_check_timings(struct omap_dss_device *dssdev, +int omapdss_venc_check_timings(struct omap_dss_output *out, struct omap_video_timings *timings); -u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev); -int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss); -void omapdss_venc_set_type(struct omap_dss_device *dssdev, +u32 omapdss_venc_get_wss(struct omap_dss_output *out); +int omapdss_venc_set_wss(struct omap_dss_output *out, u32 wss); +void omapdss_venc_set_type(struct omap_dss_output *out, enum omap_dss_venc_type type); -void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev, +void omapdss_venc_invert_vid_out_polarity(struct omap_dss_output *out, bool invert_polarity); int venc_panel_init(void); void venc_panel_exit(void); diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 264c5ec..7b399e7 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -426,7 +426,7 @@ static const struct venc_config *venc_timings_to_config( return NULL; } -static int venc_power_on(struct omap_dss_device *dssdev) +static int venc_power_on(struct omap_dss_output *out) { u32 l; int r; @@ -453,13 +453,13 @@ static int venc_power_on(struct omap_dss_device *dssdev) venc_write_reg(VENC_OUTPUT_CONTROL, l); - dss_mgr_set_timings(dssdev-manager, venc.timings); + dss_mgr_set_timings(out-manager, venc.timings); r = regulator_enable(venc.vdda_dac_reg); if (r) goto err1; - r = dss_mgr_enable(dssdev-manager); + r = dss_mgr_enable(out-manager); if (r) goto err2; @@ -476,12 +476,12 @@ err0: return r; } -static void venc_power_off(struct omap_dss_device *dssdev) +static void venc_power_off(struct omap_dss_output *out) { venc_write_reg(VENC_OUTPUT_CONTROL, 0); dss_set_dac_pwrdn_bgz(0); - dss_mgr_disable(dssdev-manager); + dss_mgr_disable(out-manager); regulator_disable(venc.vdda_dac_reg); @@ -494,7 +494,7 @@ unsigned long venc_get_pixel_clock(void) return 1350; } -int omapdss_venc_display_enable(struct omap_dss_device *dssdev) +int omapdss_venc_display_enable(struct omap_dss_output *out) { int r; @@ -502,23 +502,23 @@ int omapdss_venc_display_enable(struct omap_dss_device *dssdev) mutex_lock(venc.venc_lock); - if (dssdev-manager == NULL) { + if (out-manager == NULL) { DSSERR(Failed to enable display: no manager\n); r = -ENODEV; goto err0; } - r = omap_dss_start_device(dssdev); + r = omap_dss_start_device(out-device); if (r) { DSSERR(failed to start device\n); goto err0; } - if (dssdev-platform_enable) - dssdev-platform_enable(dssdev); + if (out-device-platform_enable) + out-device-platform_enable(out-device); - r = venc_power_on(dssdev); + r = venc_power_on(out); if (r)
[PATCH 17/23] OMAPDSS: HDMI: Pass outputs from panel driver to HDMI interface driver
With outputs introduces as new entities, we can now pass output pointer to functions used to configure the connected interface. These functions currently pass the omap_dss_device pointer, and extract output information via omap_dss_device. This is unnecessary, and it doesn't make sense for interface related functions to get the panel's/device's pointer, it should receive a pointer related to the connected interface, which in our case is the output entity. With the addition of outputs. There is a possibility that an omap_dss_device isn't connected to an output yet. Ensure that panel drivers call the interface functions only if outputs are non NULL. Modify HDMI functions to pass omap_dss_output pointer instead of omap_dss_device pointer. Modify the panel drivers to call the updated functions. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/dss.h| 10 +++ drivers/video/omap2/dss/hdmi.c | 50 +++--- drivers/video/omap2/dss/hdmi_panel.c | 47 3 files changed, 69 insertions(+), 38 deletions(-) diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 5fd3cc5..bfa8b4d 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -503,12 +503,12 @@ static inline unsigned long hdmi_get_pixel_clock(void) return 0; } #endif -int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); -void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); -void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev, +int omapdss_hdmi_display_enable(struct omap_dss_output *out); +void omapdss_hdmi_display_disable(struct omap_dss_output *out); +void omapdss_hdmi_display_set_timing(struct omap_dss_output *out, + struct omap_video_timings *timings); +int omapdss_hdmi_display_check_timing(struct omap_dss_output *out, struct omap_video_timings *timings); -int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, - struct omap_video_timings *timings); int omapdss_hdmi_read_edid(u8 *buf, int len); bool omapdss_hdmi_detect(void); int hdmi_panel_init(void); diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index d32dbc3..16b745c 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -405,9 +405,10 @@ unsigned long hdmi_get_pixel_clock(void) return hdmi.ip_data.cfg.timings.pixel_clock * 1000; } -static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, +static void hdmi_compute_pll(struct omap_dss_output *out, int phy, struct hdmi_pll_info *pi) { + struct omap_dss_device *dssdev = out-device; unsigned long clkin, refclk; u32 mf; @@ -456,7 +457,7 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, DSSDBG(range = %d sd = %d\n, pi-dcofreq, pi-regsd); } -static int hdmi_power_on(struct omap_dss_device *dssdev) +static int hdmi_power_on(struct omap_dss_output *out) { int r; struct omap_video_timings *p; @@ -466,7 +467,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) if (r) return r; - dss_mgr_disable(dssdev-manager); + dss_mgr_disable(out-manager); p = hdmi.ip_data.cfg.timings; @@ -474,7 +475,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) phy = p-pixel_clock; - hdmi_compute_pll(dssdev, phy, hdmi.ip_data.pll_data); + hdmi_compute_pll(out, phy, hdmi.ip_data.pll_data); hdmi.ip_data.ops-video_disable(hdmi.ip_data); @@ -502,19 +503,19 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) * dynamically by user. This can be moved to single location , say * Boardfile. */ - dss_select_dispc_clk_source(dssdev-clocks.dispc.dispc_fclk_src); + dss_select_dispc_clk_source(out-device-clocks.dispc.dispc_fclk_src); /* bypass TV gamma table */ dispc_enable_gamma_table(0); /* tv size */ - dss_mgr_set_timings(dssdev-manager, p); + dss_mgr_set_timings(out-manager, p); r = hdmi.ip_data.ops-video_enable(hdmi.ip_data); if (r) goto err_vid_enable; - r = dss_mgr_enable(dssdev-manager); + r = dss_mgr_enable(out-manager); if (r) goto err_mgr_enable; @@ -531,9 +532,9 @@ err: return -EIO; } -static void hdmi_power_off(struct omap_dss_device *dssdev) +static void hdmi_power_off(struct omap_dss_output *out) { - dss_mgr_disable(dssdev-manager); + dss_mgr_disable(out-manager); hdmi.ip_data.ops-video_disable(hdmi.ip_data); hdmi.ip_data.ops-phy_disable(hdmi.ip_data); @@ -541,8 +542,8 @@ static void hdmi_power_off(struct omap_dss_device *dssdev) hdmi_runtime_put(); } -int omapdss_hdmi_display_check_timing(struct omap_dss_device
[PATCH 18/23] OMAPDSS: HDMI: Add output pointers as arguments to all functions used by hdmi panel driver
All functions of an output driver used by a panel driver should have an omap_dss_output pointer as an argument. This is needed as the function would somehow need to retrieve the output driver's private data. It may not be needed by some of the outputs for now as driver data is globally visible within them. The correct way to retrieve driver data is to extract the platform device from the output, and then extract the driver data from the platform device. Add output arguments from functions used by panel drivers which currently miss it. This will come to use when the HDMI functions retrieve the driver data in the correct manner. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/dss.h| 17 --- drivers/video/omap2/dss/hdmi.c | 16 +++--- drivers/video/omap2/dss/hdmi_panel.c | 38 +- 3 files changed, 45 insertions(+), 26 deletions(-) diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index bfa8b4d..dfbc3d9 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -509,17 +509,18 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_output *out, struct omap_video_timings *timings); int omapdss_hdmi_display_check_timing(struct omap_dss_output *out, struct omap_video_timings *timings); -int omapdss_hdmi_read_edid(u8 *buf, int len); -bool omapdss_hdmi_detect(void); +int omapdss_hdmi_read_edid(struct omap_dss_output *out, u8 *buf, int len); +bool omapdss_hdmi_detect(struct omap_dss_output *out); int hdmi_panel_init(void); void hdmi_panel_exit(void); #ifdef CONFIG_OMAP4_DSS_HDMI_AUDIO -int hdmi_audio_enable(void); -void hdmi_audio_disable(void); -int hdmi_audio_start(void); -void hdmi_audio_stop(void); -bool hdmi_mode_has_audio(void); -int hdmi_audio_config(struct omap_dss_audio *audio); +int hdmi_audio_enable(struct omap_dss_output *out); +void hdmi_audio_disable(struct omap_dss_output *out); +int hdmi_audio_start(struct omap_dss_output *out); +void hdmi_audio_stop(struct omap_dss_output *out); +bool hdmi_mode_has_audio(struct omap_dss_output *out); +int hdmi_audio_config(struct omap_dss_output *out, + struct omap_dss_audio *audio); #endif /* RFBI */ diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 16b745c..39dfc2b 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -602,7 +602,7 @@ static void hdmi_dump_regs(struct seq_file *s) mutex_unlock(hdmi.lock); } -int omapdss_hdmi_read_edid(u8 *buf, int len) +int omapdss_hdmi_read_edid(struct omap_dss_output *out, u8 *buf, int len) { int r; @@ -619,7 +619,7 @@ int omapdss_hdmi_read_edid(u8 *buf, int len) return r; } -bool omapdss_hdmi_detect(void) +bool omapdss_hdmi_detect(struct omap_dss_output *out) { int r; @@ -829,35 +829,35 @@ int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts) return 0; } -int hdmi_audio_enable(void) +int hdmi_audio_enable(struct omap_dss_output *out) { DSSDBG(audio_enable\n); return hdmi.ip_data.ops-audio_enable(hdmi.ip_data); } -void hdmi_audio_disable(void) +void hdmi_audio_disable(struct omap_dss_output *out) { DSSDBG(audio_disable\n); hdmi.ip_data.ops-audio_disable(hdmi.ip_data); } -int hdmi_audio_start(void) +int hdmi_audio_start(struct omap_dss_output *out) { DSSDBG(audio_start\n); return hdmi.ip_data.ops-audio_start(hdmi.ip_data); } -void hdmi_audio_stop(void) +void hdmi_audio_stop(struct omap_dss_output *out) { DSSDBG(audio_stop\n); hdmi.ip_data.ops-audio_stop(hdmi.ip_data); } -bool hdmi_mode_has_audio(void) +bool hdmi_mode_has_audio(struct omap_dss_output *out) { if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI) return true; @@ -865,7 +865,7 @@ bool hdmi_mode_has_audio(void) return false; } -int hdmi_audio_config(struct omap_dss_audio *audio) +int hdmi_audio_config(struct omap_dss_output *out, struct omap_dss_audio *audio) { return hdmi.ip_data.ops-audio_config(hdmi.ip_data, audio); } diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c index fb35bbb..532882d 100644 --- a/drivers/video/omap2/dss/hdmi_panel.c +++ b/drivers/video/omap2/dss/hdmi_panel.c @@ -78,21 +78,25 @@ static void hdmi_panel_remove(struct omap_dss_device *dssdev) #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev) { + struct omap_dss_output *out = dssdev-output; unsigned long flags; int r; + if (out == NULL) + return -ENODEV; + mutex_lock(hdmi.lock); spin_lock_irqsave(hdmi.audio_lock, flags); /* enable audio only if the display is active and supports audio */ if (dssdev-state != OMAP_DSS_DISPLAY_ACTIVE || - !hdmi_mode_has_audio()) { +
[PATCH 19/23] OMAPDSS/OMAPFB: Change dssdev-manager references
To retrieve the manager pointer via a device, we need to now access it via the output to which the device is connected. Make this change in the places where such a reference is made. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/display.c | 11 +-- drivers/video/omap2/omapfb/omapfb-ioctl.c |4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 5bd957e..07fd1c7 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -349,8 +349,15 @@ void dss_uninit_device(struct platform_device *pdev, while ((attr = display_sysfs_attrs[i++]) != NULL) device_remove_file(dssdev-dev, attr); - if (dssdev-manager) - dssdev-manager-unset_device(dssdev-manager); + if (dssdev-output) { + if (dssdev-output-manager) { + struct omap_overlay_manager *mgr = + dssdev-output-manager; + + mgr-unset_output(mgr); + } + dssdev-output-unset_device(dssdev-output); + } } static int dss_suspend_device(struct device *dev, void *data) diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index c6cf372..25c0097 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -786,12 +786,12 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) case OMAPFB_WAITFORVSYNC: DBG(ioctl WAITFORVSYNC\n); - if (!display) { + if (!display !display-output !display-output-manager) { r = -EINVAL; break; } - r = display-manager-wait_for_vsync(display-manager); + r = display-output-manager-wait_for_vsync(display-output-manager); break; case OMAPFB_WAITFORGO: -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 20/23] OMAPDSS: MANAGER: Update display sysfs store
The display sysfs attribute's store function needs to be changed with the introduction of outputs. Providing a manager to the display isn't enough to create a link now, the manager needs and output to connect to. A manager's display store file only has the information of the manager and the desired display, it is not aware of which output should the manager connect to. Because of this, a new constraint needs to be set up when setting a display via this sysfs file. The constraint is that the desired display should already be connected to an output before calling this sysfs function. This might break some existing user space stuff which uses sysfs directly. But in most cases dss_recheck_connections will connect displays to floating outputs. DSS sysfs files are being planned to be remove anyway, so it's not much of a harm. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/manager.c | 25 - 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index fd39f66..d808ce2 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -74,18 +74,33 @@ static ssize_t manager_display_store(struct omap_overlay_manager *mgr, if (dssdev) DSSDBG(display %s found\n, dssdev-name); - if (mgr-get_device(mgr)) { - r = mgr-unset_device(mgr); + if (mgr-output) { + if (mgr-output-device) { + r = mgr-output-unset_device(mgr-output); + if (r) { + goto put_device; + DSSERR(failed to unset device from output\n); + } + } + + r = mgr-unset_output(mgr); if (r) { - DSSERR(failed to unset display\n); + DSSERR(failed to unset current output\n); goto put_device; } } if (dssdev) { - r = mgr-set_device(mgr, dssdev); + struct omap_dss_output *out = dssdev-output; + + if (!out) { + DSSERR(no output connected to device\n); + goto put_device; + } + + r = mgr-set_output(mgr, out); if (r) { - DSSERR(failed to set manager\n); + DSSERR(failed to set manager output\n); goto put_device; } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 21/23] OMAPDSS: MANAGER: Get device via output
A manager is not connected to a device directly any more. It first connects to an output, and then to the display. Update the manager's get_device op to return the device via the connected output. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/manager.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index d808ce2..d14ffc5 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -509,7 +509,7 @@ static struct kobj_type manager_ktype = { static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr) { - return mgr-device; + return mgr-output ? mgr-output-device : NULL; } static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 22/23] OMAPDSS: APPLY: Remove omap_dss_device references from dss_ovl_enable/disable
An overlay isn't allowed to be enabled/disabled if it isn't connected to an omap_dss_device. This requirement isn't needed any more. An overlay can be enabled/disabled as long as it has an output connected to it. The output may not be connected to a device, but we can be assured that the connected manager's output is in use by an output interface. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/apply.c |6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 8a05cbc..d584f0c 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -1607,8 +1607,7 @@ int dss_ovl_enable(struct omap_overlay *ovl) goto err1; } - if (ovl-manager == NULL || - ovl-manager-get_device(ovl-manager) == NULL) { + if (ovl-manager == NULL || ovl-manager-output == NULL) { r = -EINVAL; goto err1; } @@ -1677,8 +1676,7 @@ int dss_ovl_disable(struct omap_overlay *ovl) goto err; } - if (ovl-manager == NULL || - ovl-manager-get_device(ovl-manager) == NULL) { + if (ovl-manager == NULL || ovl-manager-output == NULL) { r = -EINVAL; goto err; } -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 23/23] OMAPDSS: Remove old way of setting manager and device links
Now that an omap_dss_output can be used to link between managers and devices, we can remove the old way of setting manager and device links. This involves removing the device and manager pointers from omap_overlay_manager and omap_dss_device respectively, and removing the set_device/unset_device ops from omap_overlay_manager. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/dss/apply.c | 64 - drivers/video/omap2/dss/manager.c |2 -- include/video/omapdss.h |5 --- 3 files changed, 71 deletions(-) diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index d584f0c..0ae70ab 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -1247,70 +1247,6 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr, spin_unlock_irqrestore(data_lock, flags); } -int dss_mgr_set_device(struct omap_overlay_manager *mgr, - struct omap_dss_device *dssdev) -{ - int r; - - mutex_lock(apply_lock); - - if (dssdev-manager) { - DSSERR(display '%s' already has a manager '%s'\n, - dssdev-name, dssdev-manager-name); - r = -EINVAL; - goto err; - } - - if ((mgr-supported_displays dssdev-type) == 0) { - DSSERR(display '%s' does not support manager '%s'\n, - dssdev-name, mgr-name); - r = -EINVAL; - goto err; - } - - dssdev-manager = mgr; - mgr-device = dssdev; - - mutex_unlock(apply_lock); - - return 0; -err: - mutex_unlock(apply_lock); - return r; -} - -int dss_mgr_unset_device(struct omap_overlay_manager *mgr) -{ - int r; - - mutex_lock(apply_lock); - - if (!mgr-device) { - DSSERR(failed to unset display, display not set.\n); - r = -EINVAL; - goto err; - } - - /* -* Don't allow currently enabled displays to have the overlay manager -* pulled out from underneath them -*/ - if (mgr-device-state != OMAP_DSS_DISPLAY_DISABLED) { - r = -EINVAL; - goto err; - } - - mgr-device-manager = NULL; - mgr-device = NULL; - - mutex_unlock(apply_lock); - - return 0; -err: - mutex_unlock(apply_lock); - return r; -} - int dss_mgr_set_output(struct omap_overlay_manager *mgr, struct omap_dss_output *output) { diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index d14ffc5..953f5ee 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -570,8 +570,6 @@ int dss_init_overlay_managers(struct platform_device *pdev) break; } - mgr-set_device = dss_mgr_set_device; - mgr-unset_device = dss_mgr_unset_device; mgr-set_output = dss_mgr_set_output; mgr-unset_output = dss_mgr_unset_output; mgr-apply = omap_dss_mgr_apply; diff --git a/include/video/omapdss.h b/include/video/omapdss.h index b3faea7..2be7629 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -466,7 +466,6 @@ struct omap_overlay_manager { enum omap_dss_output_id supported_outputs; /* dynamic fields */ - struct omap_dss_device *device; struct omap_dss_output *output; /* @@ -480,9 +479,6 @@ struct omap_overlay_manager { * interrupt context */ - int (*set_device)(struct omap_overlay_manager *mgr, - struct omap_dss_device *dssdev); - int (*unset_device)(struct omap_overlay_manager *mgr); int (*set_output)(struct omap_overlay_manager *mgr, struct omap_dss_output *output); int (*unset_output)(struct omap_overlay_manager *mgr); @@ -634,7 +630,6 @@ struct omap_dss_device { enum omap_display_caps caps; - struct omap_overlay_manager *manager; struct omap_dss_output *output; enum omap_dss_display_state state; -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 15/23] OMAPDSS: RFBI: Add output pointers as arguments to all exported functions
All functions of an interface driver used by a panel driver should have an omap_dss_output pointer as an argument. This may not be needed by some of the interfaces now as driver data is globally visible in them. The correct way to retrieve driver data is to extract the platform device from the output, and then extract the driver data from the platform device. Add output arguments from functions used by panel drivers which currently miss it. This will come to use when the RFBI functions retrieve the driver data in the correct manner. Signed-off-by: Archit Taneja arc...@ti.com --- drivers/video/omap2/displays/panel-n8x0.c | 78 +++-- drivers/video/omap2/dss/rfbi.c| 18 --- include/video/omapdss.h | 20 +--- 3 files changed, 74 insertions(+), 42 deletions(-) diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c index 3601c59..23fbb25 100644 --- a/drivers/video/omap2/displays/panel-n8x0.c +++ b/drivers/video/omap2/displays/panel-n8x0.c @@ -88,27 +88,34 @@ struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev) } -static inline void blizzard_cmd(u8 cmd) +static inline void blizzard_cmd(struct omap_dss_device *dssdev, u8 cmd) { - omap_rfbi_write_command(cmd, 1); + omap_rfbi_write_command(dssdev-output, cmd, 1); } -static inline void blizzard_write(u8 cmd, const u8 *buf, int len) +static inline void blizzard_write(struct omap_dss_device *dssdev, u8 cmd, + const u8 *buf, int len) { - omap_rfbi_write_command(cmd, 1); - omap_rfbi_write_data(buf, len); + struct omap_dss_output *out = dssdev-output; + + omap_rfbi_write_command(out, cmd, 1); + omap_rfbi_write_data(out, buf, len); } -static inline void blizzard_read(u8 cmd, u8 *buf, int len) +static inline void blizzard_read(struct omap_dss_device *dssdev, u8 cmd, + u8 *buf, int len) { - omap_rfbi_write_command(cmd, 1); - omap_rfbi_read_data(buf, len); + struct omap_dss_output *out = dssdev-output; + + omap_rfbi_write_command(out, cmd, 1); + omap_rfbi_read_data(out, buf, len); } -static u8 blizzard_read_reg(u8 cmd) +static u8 blizzard_read_reg(struct omap_dss_device *dssdev, u8 cmd) { u8 data; - blizzard_read(cmd, data, 1); + + blizzard_read(dssdev, cmd, data, 1); return data; } @@ -156,7 +163,7 @@ static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev, omap_rfbi_configure(out); - blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18); + blizzard_write(dssdev, BLIZZARD_INPUT_WIN_X_START_0, tmp, 18); omapdss_rfbi_set_pixel_size(out, 16); omapdss_rfbi_set_data_lines(out, 16); @@ -318,8 +325,8 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev) if (r) goto err_rfbi_en; - rev = blizzard_read_reg(BLIZZARD_REV_CODE); - conf = blizzard_read_reg(BLIZZARD_CONFIG); + rev = blizzard_read_reg(dssdev, BLIZZARD_REV_CODE); + conf = blizzard_read_reg(dssdev, BLIZZARD_CONFIG); switch (rev 0xfc) { case 0x9c: @@ -536,17 +543,21 @@ static void n8x0_panel_remove(struct omap_dss_device *dssdev) static int n8x0_panel_enable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = get_drv_data(dssdev); + struct omap_dss_output *out = dssdev-output; int r; dev_dbg(dssdev-dev, enable\n); + if (out == NULL) + return -ENODEV; + mutex_lock(ddata-lock); - rfbi_bus_lock(); + rfbi_bus_lock(out); r = n8x0_panel_power_on(dssdev); - rfbi_bus_unlock(); + rfbi_bus_unlock(out); if (r) { mutex_unlock(ddata-lock); @@ -563,16 +574,20 @@ static int n8x0_panel_enable(struct omap_dss_device *dssdev) static void n8x0_panel_disable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = get_drv_data(dssdev); + struct omap_dss_output *out = dssdev-output; dev_dbg(dssdev-dev, disable\n); + if (out == NULL) + return; + mutex_lock(ddata-lock); - rfbi_bus_lock(); + rfbi_bus_lock(out); n8x0_panel_power_off(dssdev); - rfbi_bus_unlock(); + rfbi_bus_unlock(out); dssdev-state = OMAP_DSS_DISPLAY_DISABLED; @@ -582,16 +597,20 @@ static void n8x0_panel_disable(struct omap_dss_device *dssdev) static int n8x0_panel_suspend(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = get_drv_data(dssdev); + struct omap_dss_output *out = dssdev-output; dev_dbg(dssdev-dev, suspend\n); + if (out == NULL) + return -ENODEV; + mutex_lock(ddata-lock); - rfbi_bus_lock(); + rfbi_bus_lock(out); n8x0_panel_power_off(dssdev); - rfbi_bus_unlock(); + rfbi_bus_unlock(out);
[PATCH 0/2] OMAPDSS: fixes for -rc
Hi Florian, Here are two small fixes for omapfb and omapdss. The first one fixes an old bug that causes colors to be wrong on fb console. The other fixes SDI output that got broken in the previous merge window. Tomi Grazvydas Ignotas (1): OMAPFB: fix framebuffer console colors Tomi Valkeinen (1): OMAPDSS: Fix SDI PLL locking drivers/video/omap2/dss/sdi.c| 14 ++ drivers/video/omap2/omapfb/omapfb-main.c |2 +- 2 files changed, 15 insertions(+), 1 deletion(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] OMAPDSS: Fix SDI PLL locking
Commit f476ae9dab3234532d41d36beb4ba7be838fa786 (OMAPDSS: APPLY: Remove DISPC writes to manager's lcd parameters in interface) broke the SDI output, as it causes the SDI PLL locking to fail. LCLK and PCLK divisors are located in shadow registers, and we normally write them to DISPC registers when enabling the output. However, SDI uses pck-free as source clock for its PLL, and pck-free is affected by the divisors. And as we need the PLL before enabling the output, we need to write the divisors early. It seems just writing to the DISPC register is enough, and we don't need to care about the shadow register mechanism for pck-free. The exact reason for this is unknown. Signed-off-by: Tomi Valkeinen tomi.valkei...@ti.com Reported-by: Aaro Koskinen aaro.koski...@iki.fi --- drivers/video/omap2/dss/sdi.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 5d31699..f43bfe1 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -105,6 +105,20 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) sdi_config_lcd_manager(dssdev); + /* +* LCLK and PCLK divisors are located in shadow registers, and we +* normally write them to DISPC registers when enabling the output. +* However, SDI uses pck-free as source clock for its PLL, and pck-free +* is affected by the divisors. And as we need the PLL before enabling +* the output, we need to write the divisors early. +* +* It seems just writing to the DISPC register is enough, and we don't +* need to care about the shadow register mechanism for pck-free. The +* exact reason for this is unknown. +*/ + dispc_mgr_set_clock_div(dssdev-manager-id, + sdi.mgr_config.clock_info); + dss_sdi_init(dssdev-phy.sdi.datapairs); r = dss_sdi_enable(); if (r) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] OMAPFB: fix framebuffer console colors
From: Grazvydas Ignotas nota...@gmail.com omapfb does not currently set pseudo palette correctly for color depths above 16bpp, making red text invisible, command like echo -e '\e[0;31mRED' /dev/tty1 will display nothing on framebuffer console in 24bpp mode. This is because temporary variable is declared incorrectly, fix it. Signed-off-by: Grazvydas Ignotas nota...@gmail.com Cc: sta...@vger.kernel.org # v3.x Signed-off-by: Tomi Valkeinen tomi.valkei...@ti.com --- drivers/video/omap2/omapfb/omapfb-main.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 08ec1a7..fc671d3 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c @@ -1192,7 +1192,7 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green, break; if (regno 16) { - u16 pal; + u32 pal; pal = ((red (16 - var-red.length)) var-red.offset) | ((green (16 - var-green.length)) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3] spi: omap2-mcspi: At remove dont use the runtime_autosuspend calls
At remove we shouldnt be using the autosuspend timeout as we are calling pm_runtime_disable immediately after. Signed-off-by: Shubhrajyoti D shubhrajy...@ti.com --- drivers/spi/spi-omap2-mcspi.c |3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 5642111..f5bf628 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1243,8 +1243,7 @@ static int __devexit omap2_mcspi_remove(struct platform_device *pdev) mcspi = spi_master_get_devdata(master); dma_channels = mcspi-dma_channels; - pm_runtime_mark_last_busy(mcspi-dev); - pm_runtime_put_autosuspend(mcspi-dev); + pm_runtime_put_sync(mcspi-dev); pm_runtime_disable(pdev-dev); spi_unregister_master(master); -- 1.7.5.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/3] spi: omap2-mcspi: spi cleanups
This patch does the following Calls the pm_runtime_* functions directly. Remove the MOD_REG_BIT macro usage thereby removiing un-needed branch. At remove dont use the autosuspend runtime calls. Shubhrajyoti D (3): spi: omap2-mcspi: Call pm_runtime_* functions directly spi: omap2-mcspi: Remove the macro MOD_REG_BIT spi: omap2-mcspi: At remove dont use the runtime_autosuspend calls drivers/spi/spi-omap2-mcspi.c | 55 ++--- 1 files changed, 24 insertions(+), 31 deletions(-) -- 1.7.5.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] spi: omap2-mcspi: Remove the macro MOD_REG_BIT
Remove the macro MOD_REG_BIT instead make the bit field modifications directly. This deletes a branch operation in cases where the the set is predecided.While at it optimise two sequential bit clear in one step. Signed-off-by: Shubhrajyoti D shubhrajy...@ti.com --- drivers/spi/spi-omap2-mcspi.c | 28 ++-- 1 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index dd887eb..5642111 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -140,13 +140,6 @@ struct omap2_mcspi_cs { u32 chconf0; }; -#define MOD_REG_BIT(val, mask, set) do { \ - if (set) \ - val |= mask; \ - else \ - val = ~mask; \ -} while (0) - static inline void mcspi_write_reg(struct spi_master *master, int idx, u32 val) { @@ -205,7 +198,11 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi, else rw = OMAP2_MCSPI_CHCONF_DMAW; - MOD_REG_BIT(l, rw, enable); + if (enable) + l |= rw; + else + l = ~rw; + mcspi_write_chconf0(spi, l); } @@ -224,7 +221,11 @@ static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active) u32 l; l = mcspi_cached_chconf0(spi); - MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active); + if (cs_active) + l |= OMAP2_MCSPI_CHCONF_FORCE; + else + l = ~OMAP2_MCSPI_CHCONF_FORCE; + mcspi_write_chconf0(spi, l); } @@ -239,9 +240,8 @@ static void omap2_mcspi_set_master_mode(struct spi_master *master) * to single-channel master mode */ l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL); - MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0); - MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0); - MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1); + l = ~(OMAP2_MCSPI_MODULCTRL_STEST | OMAP2_MCSPI_MODULCTRL_MS); + l |= OMAP2_MCSPI_MODULCTRL_SINGLE; mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); ctx-modulctrl = l; @@ -1276,9 +1276,9 @@ static int omap2_mcspi_resume(struct device *dev) * We need to toggle CS state for OMAP take this * change in account. */ - MOD_REG_BIT(cs-chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1); + cs-chconf0 |= OMAP2_MCSPI_CHCONF_FORCE; __raw_writel(cs-chconf0, cs-base + OMAP2_MCSPI_CHCONF0); - MOD_REG_BIT(cs-chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0); + cs-chconf0 = ~OMAP2_MCSPI_CHCONF_FORCE; __raw_writel(cs-chconf0, cs-base + OMAP2_MCSPI_CHCONF0); } } -- 1.7.5.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] spi: omap2-mcspi: Call pm_runtime_* functions directly
Call the pm_runtime functions directly making room for possible pm optimisations. Also the runtime functions aren't just about enabling and disabling of clocks though it does enable clocks also. Signed-off-by: Shubhrajyoti D shubhrajy...@ti.com --- drivers/spi/spi-omap2-mcspi.c | 28 +++- 1 files changed, 11 insertions(+), 17 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 259f601..dd887eb 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -260,16 +260,6 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) list_for_each_entry(cs, ctx-cs, node) __raw_writel(cs-chconf0, cs-base + OMAP2_MCSPI_CHCONF0); } -static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi) -{ - pm_runtime_mark_last_busy(mcspi-dev); - pm_runtime_put_autosuspend(mcspi-dev); -} - -static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi) -{ - return pm_runtime_get_sync(mcspi-dev); -} static int omap2_prepare_transfer(struct spi_master *master) { @@ -848,12 +838,13 @@ static int omap2_mcspi_setup(struct spi_device *spi) return ret; } - ret = omap2_mcspi_enable_clocks(mcspi); + ret = pm_runtime_get_sync(mcspi-dev); if (ret 0) return ret; ret = omap2_mcspi_setup_transfer(spi, NULL); - omap2_mcspi_disable_clocks(mcspi); + pm_runtime_mark_last_busy(mcspi-dev); + pm_runtime_put_autosuspend(mcspi-dev); return ret; } @@ -1067,7 +1058,7 @@ static int __devinit omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) struct omap2_mcspi_regs *ctx = mcspi-ctx; int ret = 0; - ret = omap2_mcspi_enable_clocks(mcspi); + ret = pm_runtime_get_sync(mcspi-dev); if (ret 0) return ret; @@ -1076,7 +1067,8 @@ static int __devinit omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) ctx-wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN; omap2_mcspi_set_master_mode(master); - omap2_mcspi_disable_clocks(mcspi); + pm_runtime_mark_last_busy(mcspi-dev); + pm_runtime_put_autosuspend(mcspi-dev); return 0; } @@ -1251,7 +1243,8 @@ static int __devexit omap2_mcspi_remove(struct platform_device *pdev) mcspi = spi_master_get_devdata(master); dma_channels = mcspi-dma_channels; - omap2_mcspi_disable_clocks(mcspi); + pm_runtime_mark_last_busy(mcspi-dev); + pm_runtime_put_autosuspend(mcspi-dev); pm_runtime_disable(pdev-dev); spi_unregister_master(master); @@ -1276,7 +1269,7 @@ static int omap2_mcspi_resume(struct device *dev) struct omap2_mcspi_regs *ctx = mcspi-ctx; struct omap2_mcspi_cs *cs; - omap2_mcspi_enable_clocks(mcspi); + pm_runtime_get_sync(mcspi-dev); list_for_each_entry(cs, ctx-cs, node) { if ((cs-chconf0 OMAP2_MCSPI_CHCONF_FORCE) == 0) { /* @@ -1289,7 +1282,8 @@ static int omap2_mcspi_resume(struct device *dev) __raw_writel(cs-chconf0, cs-base + OMAP2_MCSPI_CHCONF0); } } - omap2_mcspi_disable_clocks(mcspi); + pm_runtime_mark_last_busy(mcspi-dev); + pm_runtime_put_autosuspend(mcspi-dev); return 0; } #else -- 1.7.5.4 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/3] spi: omap2-mcspi: Call pm_runtime_* functions directly
On Tue, Aug 21, 2012 at 11:47:42AM +0530, Shubhrajyoti D wrote: Call the pm_runtime functions directly making room for possible pm optimisations. Also the runtime functions aren't just about enabling and disabling of clocks though it does enable clocks also. Signed-off-by: Shubhrajyoti D shubhrajy...@ti.com Acked-by: Felipe Balbi ba...@ti.com --- drivers/spi/spi-omap2-mcspi.c | 28 +++- 1 files changed, 11 insertions(+), 17 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 259f601..dd887eb 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -260,16 +260,6 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) list_for_each_entry(cs, ctx-cs, node) __raw_writel(cs-chconf0, cs-base + OMAP2_MCSPI_CHCONF0); } -static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi) -{ - pm_runtime_mark_last_busy(mcspi-dev); - pm_runtime_put_autosuspend(mcspi-dev); -} - -static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi) -{ - return pm_runtime_get_sync(mcspi-dev); -} static int omap2_prepare_transfer(struct spi_master *master) { @@ -848,12 +838,13 @@ static int omap2_mcspi_setup(struct spi_device *spi) return ret; } - ret = omap2_mcspi_enable_clocks(mcspi); + ret = pm_runtime_get_sync(mcspi-dev); if (ret 0) return ret; ret = omap2_mcspi_setup_transfer(spi, NULL); - omap2_mcspi_disable_clocks(mcspi); + pm_runtime_mark_last_busy(mcspi-dev); + pm_runtime_put_autosuspend(mcspi-dev); return ret; } @@ -1067,7 +1058,7 @@ static int __devinit omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) struct omap2_mcspi_regs *ctx = mcspi-ctx; int ret = 0; - ret = omap2_mcspi_enable_clocks(mcspi); + ret = pm_runtime_get_sync(mcspi-dev); if (ret 0) return ret; @@ -1076,7 +1067,8 @@ static int __devinit omap2_mcspi_master_setup(struct omap2_mcspi *mcspi) ctx-wakeupenable = OMAP2_MCSPI_WAKEUPENABLE_WKEN; omap2_mcspi_set_master_mode(master); - omap2_mcspi_disable_clocks(mcspi); + pm_runtime_mark_last_busy(mcspi-dev); + pm_runtime_put_autosuspend(mcspi-dev); return 0; } @@ -1251,7 +1243,8 @@ static int __devexit omap2_mcspi_remove(struct platform_device *pdev) mcspi = spi_master_get_devdata(master); dma_channels = mcspi-dma_channels; - omap2_mcspi_disable_clocks(mcspi); + pm_runtime_mark_last_busy(mcspi-dev); + pm_runtime_put_autosuspend(mcspi-dev); pm_runtime_disable(pdev-dev); spi_unregister_master(master); @@ -1276,7 +1269,7 @@ static int omap2_mcspi_resume(struct device *dev) struct omap2_mcspi_regs *ctx = mcspi-ctx; struct omap2_mcspi_cs *cs; - omap2_mcspi_enable_clocks(mcspi); + pm_runtime_get_sync(mcspi-dev); list_for_each_entry(cs, ctx-cs, node) { if ((cs-chconf0 OMAP2_MCSPI_CHCONF_FORCE) == 0) { /* @@ -1289,7 +1282,8 @@ static int omap2_mcspi_resume(struct device *dev) __raw_writel(cs-chconf0, cs-base + OMAP2_MCSPI_CHCONF0); } } - omap2_mcspi_disable_clocks(mcspi); + pm_runtime_mark_last_busy(mcspi-dev); + pm_runtime_put_autosuspend(mcspi-dev); return 0; } #else -- 1.7.5.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- balbi signature.asc Description: Digital signature
Re: [PATCH 2/3] spi: omap2-mcspi: Remove the macro MOD_REG_BIT
On Tue, Aug 21, 2012 at 11:47:43AM +0530, Shubhrajyoti D wrote: Remove the macro MOD_REG_BIT instead make the bit field modifications directly. This deletes a branch operation in cases where the the set is predecided.While at it optimise two sequential bit clear in one step. ^^ you need a space here, besides you can add the ack below Signed-off-by: Shubhrajyoti D shubhrajy...@ti.com Acked-by: Felipe Balbi ba...@ti.com --- drivers/spi/spi-omap2-mcspi.c | 28 ++-- 1 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index dd887eb..5642111 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -140,13 +140,6 @@ struct omap2_mcspi_cs { u32 chconf0; }; -#define MOD_REG_BIT(val, mask, set) do { \ - if (set) \ - val |= mask; \ - else \ - val = ~mask; \ -} while (0) - static inline void mcspi_write_reg(struct spi_master *master, int idx, u32 val) { @@ -205,7 +198,11 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi, else rw = OMAP2_MCSPI_CHCONF_DMAW; - MOD_REG_BIT(l, rw, enable); + if (enable) + l |= rw; + else + l = ~rw; + mcspi_write_chconf0(spi, l); } @@ -224,7 +221,11 @@ static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active) u32 l; l = mcspi_cached_chconf0(spi); - MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active); + if (cs_active) + l |= OMAP2_MCSPI_CHCONF_FORCE; + else + l = ~OMAP2_MCSPI_CHCONF_FORCE; + mcspi_write_chconf0(spi, l); } @@ -239,9 +240,8 @@ static void omap2_mcspi_set_master_mode(struct spi_master *master) * to single-channel master mode */ l = mcspi_read_reg(master, OMAP2_MCSPI_MODULCTRL); - MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_STEST, 0); - MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0); - MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1); + l = ~(OMAP2_MCSPI_MODULCTRL_STEST | OMAP2_MCSPI_MODULCTRL_MS); + l |= OMAP2_MCSPI_MODULCTRL_SINGLE; mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); ctx-modulctrl = l; @@ -1276,9 +1276,9 @@ static int omap2_mcspi_resume(struct device *dev) * We need to toggle CS state for OMAP take this * change in account. */ - MOD_REG_BIT(cs-chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1); + cs-chconf0 |= OMAP2_MCSPI_CHCONF_FORCE; __raw_writel(cs-chconf0, cs-base + OMAP2_MCSPI_CHCONF0); - MOD_REG_BIT(cs-chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0); + cs-chconf0 = ~OMAP2_MCSPI_CHCONF_FORCE; __raw_writel(cs-chconf0, cs-base + OMAP2_MCSPI_CHCONF0); } } -- 1.7.5.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- balbi signature.asc Description: Digital signature
Re: [PATCH 3/3] spi: omap2-mcspi: At remove dont use the runtime_autosuspend calls
On Tue, Aug 21, 2012 at 11:47:44AM +0530, Shubhrajyoti D wrote: At remove we shouldnt be using the autosuspend timeout as we are calling pm_runtime_disable immediately after. Signed-off-by: Shubhrajyoti D shubhrajy...@ti.com Makes sense to me: Acked-by: Felipe Balbi ba...@ti.com --- drivers/spi/spi-omap2-mcspi.c |3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 5642111..f5bf628 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1243,8 +1243,7 @@ static int __devexit omap2_mcspi_remove(struct platform_device *pdev) mcspi = spi_master_get_devdata(master); dma_channels = mcspi-dma_channels; - pm_runtime_mark_last_busy(mcspi-dev); - pm_runtime_put_autosuspend(mcspi-dev); + pm_runtime_put_sync(mcspi-dev); pm_runtime_disable(pdev-dev); spi_unregister_master(master); -- 1.7.5.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- balbi signature.asc Description: Digital signature
[RFC/PATCH 03/13] serial: omap: define helpers for pdata function pointers
this patch is in preparation to a few other changes which will align on the prototype for function pointers passed through pdata. It also helps cleaning up the driver a little by agregating checks for pdata in a single location. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 66 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index b4b95fc..c3e6fa0 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -101,6 +101,40 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up) serial_out(up, UART_FCR, 0); } +static int serial_omap_get_context_loss_count(struct uart_omap_port *up) +{ + struct omap_uart_port_info *pdata = up-pdev-dev.platform_data; + + if (!pdata-get_context_loss_count) + return 0; + + return pdata-get_context_loss_count(up-pdev-dev); +} + +static void serial_omap_set_forceidle(struct uart_omap_port *up) +{ + struct omap_uart_port_info *pdata = up-pdev-dev.platform_data; + + if (pdata-set_forceidle) + pdata-set_forceidle(up-pdev); +} + +static void serial_omap_set_noidle(struct uart_omap_port *up) +{ + struct omap_uart_port_info *pdata = up-pdev-dev.platform_data; + + if (pdata-set_noidle) + pdata-set_noidle(up-pdev); +} + +static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable) +{ + struct omap_uart_port_info *pdata = up-pdev-dev.platform_data; + + if (pdata-enable_wakeup) + pdata-enable_wakeup(up-pdev, enable); +} + /* * serial_omap_get_divisor - calculate divisor value * @port: uart port info @@ -177,8 +211,8 @@ static void serial_omap_stop_tx(struct uart_port *port) serial_out(up, UART_IER, up-ier); } - if (!up-use_dma pdata pdata-set_forceidle) - pdata-set_forceidle(up-pdev); + if (!up-use_dma pdata) + serial_omap_set_forceidle(up); pm_runtime_mark_last_busy(up-pdev-dev); pm_runtime_put_autosuspend(up-pdev-dev); @@ -308,7 +342,6 @@ static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up) static void serial_omap_start_tx(struct uart_port *port) { struct uart_omap_port *up = to_uart_omap_port(port); - struct omap_uart_port_info *pdata = up-pdev-dev.platform_data; struct circ_buf *xmit; unsigned int start; int ret = 0; @@ -316,8 +349,7 @@ static void serial_omap_start_tx(struct uart_port *port) if (!up-use_dma) { pm_runtime_get_sync(up-pdev-dev); serial_omap_enable_ier_thri(up); - if (pdata pdata-set_noidle) - pdata-set_noidle(up-pdev); + serial_omap_set_noidle(up); pm_runtime_mark_last_busy(up-pdev-dev); pm_runtime_put_autosuspend(up-pdev-dev); return; @@ -1648,28 +1680,26 @@ static int serial_omap_runtime_suspend(struct device *dev) if (!up) return -EINVAL; - if (!pdata || !pdata-enable_wakeup) + if (!pdata) return 0; - if (pdata-get_context_loss_count) - up-context_loss_cnt = pdata-get_context_loss_count(dev); + up-context_loss_cnt = serial_omap_get_context_loss_count(up); if (device_may_wakeup(dev)) { if (!up-wakeups_enabled) { - pdata-enable_wakeup(up-pdev, true); + serial_omap_enable_wakeup(up, true); up-wakeups_enabled = true; } } else { if (up-wakeups_enabled) { - pdata-enable_wakeup(up-pdev, false); + serial_omap_enable_wakeup(up, false); up-wakeups_enabled = false; } } /* Errata i291 */ - if (up-use_dma pdata-set_forceidle - (up-errata UART_ERRATA_i291_DMA_FORCEIDLE)) - pdata-set_forceidle(up-pdev); + if (up-use_dma (up-errata UART_ERRATA_i291_DMA_FORCEIDLE)) + serial_omap_set_forceidle(up); up-latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; schedule_work(up-qos_work); @@ -1683,17 +1713,15 @@ static int serial_omap_runtime_resume(struct device *dev) struct omap_uart_port_info *pdata = dev-platform_data; if (up pdata) { - if (pdata-get_context_loss_count) { - u32 loss_cnt = pdata-get_context_loss_count(dev); + u32 loss_cnt = serial_omap_get_context_loss_count(up); if (up-context_loss_cnt != loss_cnt) serial_omap_restore_context(up); - } /* Errata i291 */ - if (up-use_dma
[RFC/PATCH 07/13] serial: omap: simplify IRQ handling
quite a few changes here, though they are pretty obvious. In summary we're making sure to detect which interrupt type we need to handle before calling the underlying interrupt handling procedure. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 47 ++-- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 4d74a9b..1ca08b8 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -350,32 +350,55 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id) { struct uart_omap_port *up = dev_id; unsigned int iir, lsr; + unsigned int type; unsigned long flags; + spin_lock_irqsave(up-port.lock, flags); pm_runtime_get_sync(up-dev); iir = serial_in(up, UART_IIR); - if (iir UART_IIR_NO_INT) { - pm_runtime_mark_last_busy(up-dev); - pm_runtime_put_autosuspend(up-dev); - return IRQ_HANDLED; - } +again: + if (iir UART_IIR_NO_INT) + goto out; - spin_lock_irqsave(up-port.lock, flags); lsr = serial_in(up, UART_LSR); - if (iir UART_IIR_RLSI) { + + /* extract IRQ type from IIR register */ + type = iir 0x3e; + + switch (type) { + case UART_IIR_MSI: + check_modem_status(up); + break; + case UART_IIR_THRI: + if (lsr UART_LSR_THRE) + transmit_chars(up); + break; + case UART_IIR_RDI: if (lsr UART_LSR_DR) receive_chars(up, lsr); + break; + case UART_IIR_RLSI: + if (lsr UART_LSR_BRK_ERROR_BITS) + receive_chars(up, lsr); + break; + case UART_IIR_RX_TIMEOUT: + receive_chars(up, lsr); + break; + case UART_IIR_CTS_RTS_DSR: + iir = serial_in(up, UART_IIR); + goto again; + case UART_IIR_XOFF: + /* FALLTHROUGH */ + default: + break; } - check_modem_status(up); - if ((lsr UART_LSR_THRE) (iir UART_IIR_THRI)) - transmit_chars(up); - +out: spin_unlock_irqrestore(up-port.lock, flags); pm_runtime_mark_last_busy(up-dev); pm_runtime_put_autosuspend(up-dev); - up-port_activity = jiffies; + return IRQ_HANDLED; } -- 1.7.12.rc3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC/PATCH 11/13] serial: omap: set dev-drvdata before enabling pm_runtime
by the time we call our first pm_runtme_get_sync() after enable pm_runtime, our resume method might be called. To avoid problems, we must make sure that our dev-drvdata is set correctly before our resume method gets called. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 458d77c..ba9cdf1 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1298,6 +1298,7 @@ static int serial_omap_probe(struct platform_device *pdev) serial_omap_uart_wq = create_singlethread_workqueue(up-name); INIT_WORK(up-qos_work, serial_omap_uart_qos_work); + platform_set_drvdata(pdev, up); pm_runtime_use_autosuspend(pdev-dev); pm_runtime_set_autosuspend_delay(pdev-dev, omap_up_info-autosuspend_timeout); @@ -1317,7 +1318,6 @@ static int serial_omap_probe(struct platform_device *pdev) pm_runtime_mark_last_busy(up-dev); pm_runtime_put_autosuspend(up-dev); - platform_set_drvdata(pdev, up); return 0; err_add_port: -- 1.7.12.rc3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC/PATCH 10/13] serial: omap: stick to put_autosuspend
Everytime we're done using our TTY, we want the pm timer to be reinitilized. By sticking to pm_runtime_pm_autosuspend() we make sure that this will always be the case. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 33 ++--- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 6ea24c5..458d77c 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -164,7 +164,8 @@ static void serial_omap_enable_ms(struct uart_port *port) pm_runtime_get_sync(up-dev); up-ier |= UART_IER_MSI; serial_out(up, UART_IER, up-ier); - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); } static void serial_omap_stop_tx(struct uart_port *port) @@ -412,7 +413,8 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port) spin_lock_irqsave(up-port.lock, flags); ret = serial_in(up, UART_LSR) UART_LSR_TEMT ? TIOCSER_TEMT : 0; spin_unlock_irqrestore(up-port.lock, flags); - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); return ret; } @@ -424,7 +426,8 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port) pm_runtime_get_sync(up-dev); status = check_modem_status(up); - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); dev_dbg(up-port.dev, serial_omap_get_mctrl+%d\n, up-port.line); @@ -460,7 +463,8 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) up-mcr = serial_in(up, UART_MCR); up-mcr |= mcr; serial_out(up, UART_MCR, up-mcr); - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); } static void serial_omap_break_ctl(struct uart_port *port, int break_state) @@ -477,7 +481,8 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state) up-lcr = ~UART_LCR_SBC; serial_out(up, UART_LCR, up-lcr); spin_unlock_irqrestore(up-port.lock, flags); - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); } static int serial_omap_startup(struct uart_port *port) @@ -575,7 +580,8 @@ static void serial_omap_shutdown(struct uart_port *port) if (serial_in(up, UART_LSR) UART_LSR_DR) (void) serial_in(up, UART_RX); - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); free_irq(up-port.irq, up); } @@ -846,7 +852,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, serial_omap_configure_xonxoff(up, termios); spin_unlock_irqrestore(up-port.lock, flags); - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); dev_dbg(up-port.dev, serial_omap_set_termios+%d\n, up-port.line); } @@ -877,7 +884,8 @@ serial_omap_pm(struct uart_port *port, unsigned int state, pm_runtime_allow(up-dev); } - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); } static void serial_omap_release_port(struct uart_port *port) @@ -959,7 +967,8 @@ static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch) pm_runtime_get_sync(up-dev); wait_for_xmitr(up); serial_out(up, UART_TX, ch); - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); } static int serial_omap_poll_get_char(struct uart_port *port) @@ -973,7 +982,8 @@ static int serial_omap_poll_get_char(struct uart_port *port) return NO_POLL_CHAR; status = serial_in(up, UART_RX); - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); return status; } @@ -1305,7 +1315,8 @@ static int serial_omap_probe(struct platform_device *pdev) if (ret != 0) goto err_add_port; - pm_runtime_put(pdev-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); platform_set_drvdata(pdev, up); return 0; -- 1.7.12.rc3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC/PATCH 13/13] serial: omap: make sure to suspend device before remove
before removing the driver, let's make sure to force device into a suspended state in order to conserve power. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 25d2055..f849ab9 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1334,6 +1334,7 @@ static int serial_omap_remove(struct platform_device *dev) { struct uart_omap_port *up = platform_get_drvdata(dev); + pm_runtime_put_sync(up-dev); pm_runtime_disable(up-dev); uart_remove_one_port(serial_omap_reg, up-port); pm_qos_remove_request(up-pm_qos_request); -- 1.7.12.rc3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC/PATCH 12/13] serial: omap: drop unnecessary check from remove
if platform_get_drvdata() returns NULL, that's quite a nasty bug on the driver which we want to catch ASAP. Otherwise, that check is hugely unneeded. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 9 +++-- 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index ba9cdf1..25d2055 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1334,13 +1334,10 @@ static int serial_omap_remove(struct platform_device *dev) { struct uart_omap_port *up = platform_get_drvdata(dev); - if (up) { - pm_runtime_disable(up-dev); - uart_remove_one_port(serial_omap_reg, up-port); - pm_qos_remove_request(up-pm_qos_request); - } + pm_runtime_disable(up-dev); + uart_remove_one_port(serial_omap_reg, up-port); + pm_qos_remove_request(up-pm_qos_request); - platform_set_drvdata(dev, NULL); return 0; } -- 1.7.12.rc3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC/PATCH 05/13] serial: omap: drop DMA support
The current support is known to be broken and a later patch will come re-adding it using dma engine API. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 330 ++- 1 file changed, 12 insertions(+), 318 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index fb81366..4d74a9b 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -33,14 +33,12 @@ #include linux/tty.h #include linux/tty_flip.h #include linux/io.h -#include linux/dma-mapping.h #include linux/clk.h #include linux/serial_core.h #include linux/irq.h #include linux/pm_runtime.h #include linux/of.h -#include plat/dma.h #include plat/dmtimer.h #include plat/omap-serial.h @@ -74,9 +72,6 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; /* Forward declaration of functions */ -static void uart_tx_dma_callback(int lch, u16 ch_status, void *data); -static void serial_omap_rxdma_poll(unsigned long uart_no); -static int serial_omap_start_rxdma(struct uart_omap_port *up); static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1); static struct workqueue_struct *serial_omap_uart_wq; @@ -160,19 +155,6 @@ serial_omap_get_divisor(struct uart_port *port, unsigned int baud) return port-uartclk/(baud * divisor); } -static void serial_omap_stop_rxdma(struct uart_omap_port *up) -{ - if (up-uart_dma.rx_dma_used) { - del_timer(up-uart_dma.rx_timer); - omap_stop_dma(up-uart_dma.rx_dma_channel); - omap_free_dma(up-uart_dma.rx_dma_channel); - up-uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; - up-uart_dma.rx_dma_used = false; - pm_runtime_mark_last_busy(up-dev); - pm_runtime_put_autosuspend(up-dev); - } -} - static void serial_omap_enable_ms(struct uart_port *port) { struct uart_omap_port *up = to_uart_omap_port(port); @@ -188,22 +170,6 @@ static void serial_omap_enable_ms(struct uart_port *port) static void serial_omap_stop_tx(struct uart_port *port) { struct uart_omap_port *up = to_uart_omap_port(port); - struct omap_uart_port_info *pdata = up-dev-platform_data; - - if (up-use_dma - up-uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) { - /* -* Check if dma is still active. If yes do nothing, -* return. Else stop dma -*/ - if (omap_get_dma_active_status(up-uart_dma.tx_dma_channel)) - return; - omap_stop_dma(up-uart_dma.tx_dma_channel); - omap_free_dma(up-uart_dma.tx_dma_channel); - up-uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE; - pm_runtime_mark_last_busy(up-dev); - pm_runtime_put_autosuspend(up-dev); - } pm_runtime_get_sync(up-dev); if (up-ier UART_IER_THRI) { @@ -211,8 +177,7 @@ static void serial_omap_stop_tx(struct uart_port *port) serial_out(up, UART_IER, up-ier); } - if (!up-use_dma pdata) - serial_omap_set_forceidle(up); + serial_omap_set_forceidle(up); pm_runtime_mark_last_busy(up-dev); pm_runtime_put_autosuspend(up-dev); @@ -223,8 +188,6 @@ static void serial_omap_stop_rx(struct uart_port *port) struct uart_omap_port *up = to_uart_omap_port(port); pm_runtime_get_sync(up-dev); - if (up-use_dma) - serial_omap_stop_rxdma(up); up-ier = ~UART_IER_RLSI; up-port.read_status_mask = ~UART_LSR_DR; serial_out(up, UART_IER, up-ier); @@ -342,67 +305,12 @@ static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up) static void serial_omap_start_tx(struct uart_port *port) { struct uart_omap_port *up = to_uart_omap_port(port); - struct circ_buf *xmit; - unsigned int start; - int ret = 0; - - if (!up-use_dma) { - pm_runtime_get_sync(up-dev); - serial_omap_enable_ier_thri(up); - serial_omap_set_noidle(up); - pm_runtime_mark_last_busy(up-dev); - pm_runtime_put_autosuspend(up-dev); - return; - } - - if (up-uart_dma.tx_dma_used) - return; - - xmit = up-port.state-xmit; - - if (up-uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) { - pm_runtime_get_sync(up-dev); - ret = omap_request_dma(up-uart_dma.uart_dma_tx, - UART Tx DMA, - (void *)uart_tx_dma_callback, up, - (up-uart_dma.tx_dma_channel)); - if (ret 0) { - serial_omap_enable_ier_thri(up); - return; - } - } - spin_lock((up-uart_dma.tx_lock)); - up-uart_dma.tx_dma_used =
[RFC/PATCH 00/13] OMAP UART patches
Hi guys, here's a series of cleanup patches to the OMAP serial driver. A later series could be made re-implementing DMA using the DMA Engine API. Note that for RX DMA we could be using RX Timeout IRQ as a hint that we better use PIO instead ;-) All patches were tested on my pandaboard, but I'd really like to receive Tested-by on other platforms. After this goes in, I'll probably try to get UART wakeup working again and only after that look at DMA. cheers Felipe Balbi (13): serial: omap: define and use to_uart_omap_port() serial: omap: always return IRQ_HANDLED serial: omap: define helpers for pdata function pointers serial: omap: don't access the platform_device serial: omap: drop DMA support serial: add OMAP-specific defines serial: omap: simplify IRQ handling serial: omap: refactor receive_chars() into rdi/rlsi handlers serial: omap: move THRE check to transmit_chars() serial: omap: stick to put_autosuspend serial: omap: set dev-drvdata before enabling pm_runtime serial: omap: drop unnecessary check from remove serial: omap: make sure to suspend device before remove arch/arm/mach-omap2/serial.c | 15 +- arch/arm/plat-omap/include/plat/omap-serial.h | 12 +- drivers/tty/serial/omap-serial.c | 707 +- include/linux/serial_reg.h| 4 + 4 files changed, 250 insertions(+), 488 deletions(-) -- 1.7.12.rc3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC/PATCH 01/13] serial: omap: define and use to_uart_omap_port()
current code only works because struct uart_port is the first member on the uart_omap_port structure. If, for whatever reason, someone puts another member as the first of the structure, that cast won't work anymore. In order to be safe, let's use a container_of() which, for now, gets optimized into a cast anyway. Signed-off-by: Felipe Balbi ba...@ti.com --- arch/arm/plat-omap/include/plat/omap-serial.h | 2 ++ drivers/tty/serial/omap-serial.c | 36 +-- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index 1a52725..f3b35d9 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -137,4 +137,6 @@ struct uart_omap_port { struct work_struct qos_work; }; +#define to_uart_omap_port(p) ((container_of((p), struct uart_omap_port, port))) + #endif /* __OMAP_SERIAL_H__ */ diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index d3cda0c..5c0d0bc 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -141,7 +141,7 @@ static void serial_omap_stop_rxdma(struct uart_omap_port *up) static void serial_omap_enable_ms(struct uart_port *port) { - struct uart_omap_port *up = (struct uart_omap_port *)port; + struct uart_omap_port *up = to_uart_omap_port(port); dev_dbg(up-port.dev, serial_omap_enable_ms+%d\n, up-port.line); @@ -153,7 +153,7 @@ static void serial_omap_enable_ms(struct uart_port *port) static void serial_omap_stop_tx(struct uart_port *port) { - struct uart_omap_port *up = (struct uart_omap_port *)port; + struct uart_omap_port *up = to_uart_omap_port(port); struct omap_uart_port_info *pdata = up-pdev-dev.platform_data; if (up-use_dma @@ -186,7 +186,7 @@ static void serial_omap_stop_tx(struct uart_port *port) static void serial_omap_stop_rx(struct uart_port *port) { - struct uart_omap_port *up = (struct uart_omap_port *)port; + struct uart_omap_port *up = to_uart_omap_port(port); pm_runtime_get_sync(up-pdev-dev); if (up-use_dma) @@ -307,7 +307,7 @@ static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up) static void serial_omap_start_tx(struct uart_port *port) { - struct uart_omap_port *up = (struct uart_omap_port *)port; + struct uart_omap_port *up = to_uart_omap_port(port); struct omap_uart_port_info *pdata = up-pdev-dev.platform_data; struct circ_buf *xmit; unsigned int start; @@ -449,7 +449,7 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id) static unsigned int serial_omap_tx_empty(struct uart_port *port) { - struct uart_omap_port *up = (struct uart_omap_port *)port; + struct uart_omap_port *up = to_uart_omap_port(port); unsigned long flags = 0; unsigned int ret = 0; @@ -464,7 +464,7 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port) static unsigned int serial_omap_get_mctrl(struct uart_port *port) { - struct uart_omap_port *up = (struct uart_omap_port *)port; + struct uart_omap_port *up = to_uart_omap_port(port); unsigned int status; unsigned int ret = 0; @@ -487,7 +487,7 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port) static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) { - struct uart_omap_port *up = (struct uart_omap_port *)port; + struct uart_omap_port *up = to_uart_omap_port(port); unsigned char mcr = 0; dev_dbg(up-port.dev, serial_omap_set_mctrl+%d\n, up-port.line); @@ -511,7 +511,7 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl) static void serial_omap_break_ctl(struct uart_port *port, int break_state) { - struct uart_omap_port *up = (struct uart_omap_port *)port; + struct uart_omap_port *up = to_uart_omap_port(port); unsigned long flags = 0; dev_dbg(up-port.dev, serial_omap_break_ctl+%d\n, up-port.line); @@ -528,7 +528,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state) static int serial_omap_startup(struct uart_port *port) { - struct uart_omap_port *up = (struct uart_omap_port *)port; + struct uart_omap_port *up = to_uart_omap_port(port); unsigned long flags = 0; int retval; @@ -606,7 +606,7 @@ static int serial_omap_startup(struct uart_port *port) static void serial_omap_shutdown(struct uart_port *port) { - struct uart_omap_port *up = (struct uart_omap_port *)port; + struct uart_omap_port *up = to_uart_omap_port(port); unsigned long flags = 0; dev_dbg(up-port.dev, serial_omap_shutdown+%d\n, up-port.line); @@ -721,7 +721,7 @@ static void serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
[RFC/PATCH 06/13] serial: add OMAP-specific defines
OMAP has some extra Interrupt types which can be really useful for SW. Let's define them so we can later use those in OMAP's serial driver. Signed-off-by: Felipe Balbi ba...@ti.com --- include/linux/serial_reg.h | 4 1 file changed, 4 insertions(+) diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h index 8ce70d7..5ed325e 100644 --- a/include/linux/serial_reg.h +++ b/include/linux/serial_reg.h @@ -40,6 +40,10 @@ #define UART_IIR_BUSY 0x07 /* DesignWare APB Busy Detect */ +#define UART_IIR_RX_TIMEOUT0x0c /* OMAP RX Timeout interrupt */ +#define UART_IIR_XOFF 0x10 /* OMAP XOFF/Special Character */ +#define UART_IIR_CTS_RTS_DSR 0x20 /* OMAP CTS/RTS/DSR Change */ + #define UART_FCR 2 /* Out: FIFO Control Register */ #define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ #define UART_FCR_CLEAR_RCVR0x02 /* Clear the RCVR FIFO */ -- 1.7.12.rc3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC/PATCH 09/13] serial: omap: move THRE check to transmit_chars()
since all other IRQ types now do all necessary checks inside their handlers, transmit_chars() was the only one left expecting serial_omap_irq() to check THRE for it. We can move THRE check to transmit_chars() in order to make serial_omap_irq() more uniform. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 74a4f0a..6ea24c5 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -195,11 +195,14 @@ static void serial_omap_stop_rx(struct uart_port *port) pm_runtime_put_autosuspend(up-dev); } -static void transmit_chars(struct uart_omap_port *up) +static void transmit_chars(struct uart_omap_port *up, unsigned int lsr) { struct circ_buf *xmit = up-port.state-xmit; int count; + if (!(lsr UART_LSR_THRE)) + return; + if (up-port.x_char) { serial_out(up, UART_TX, up-port.x_char); up-port.icount.tx++; @@ -367,8 +370,7 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id) check_modem_status(up); break; case UART_IIR_THRI: - if (lsr UART_LSR_THRE) - transmit_chars(up); + transmit_chars(up, lsr); break; case UART_IIR_RX_TIMEOUT: /* FALLTHROUGH */ -- 1.7.12.rc3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC/PATCH 08/13] serial: omap: refactor receive_chars() into rdi/rlsi handlers
receive_chars() was getting too big and too difficult to follow. By splitting it into separate RDI and RSLI handlers, we have smaller functions which are easy to understand and only touch the pieces which they need to touch. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 203 +++ 1 file changed, 100 insertions(+), 103 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 1ca08b8..74a4f0a 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -195,74 +195,6 @@ static void serial_omap_stop_rx(struct uart_port *port) pm_runtime_put_autosuspend(up-dev); } -static inline void receive_chars(struct uart_omap_port *up, - unsigned int *status) -{ - struct tty_struct *tty = up-port.state-port.tty; - unsigned int flag, lsr = *status; - unsigned char ch = 0; - int max_count = 256; - - do { - if (likely(lsr UART_LSR_DR)) - ch = serial_in(up, UART_RX); - flag = TTY_NORMAL; - up-port.icount.rx++; - - if (unlikely(lsr UART_LSR_BRK_ERROR_BITS)) { - /* -* For statistics only -*/ - if (lsr UART_LSR_BI) { - lsr = ~(UART_LSR_FE | UART_LSR_PE); - up-port.icount.brk++; - /* -* We do the SysRQ and SAK checking -* here because otherwise the break -* may get masked by ignore_status_mask -* or read_status_mask. -*/ - if (uart_handle_break(up-port)) - goto ignore_char; - } else if (lsr UART_LSR_PE) { - up-port.icount.parity++; - } else if (lsr UART_LSR_FE) { - up-port.icount.frame++; - } - - if (lsr UART_LSR_OE) - up-port.icount.overrun++; - - /* -* Mask off conditions which should be ignored. -*/ - lsr = up-port.read_status_mask; - -#ifdef CONFIG_SERIAL_OMAP_CONSOLE - if (up-port.line == up-port.cons-index) { - /* Recover the break flag from console xmit */ - lsr |= up-lsr_break_flag; - } -#endif - if (lsr UART_LSR_BI) - flag = TTY_BREAK; - else if (lsr UART_LSR_PE) - flag = TTY_PARITY; - else if (lsr UART_LSR_FE) - flag = TTY_FRAME; - } - - if (uart_handle_sysrq_char(up-port, ch)) - goto ignore_char; - uart_insert_char(up-port, lsr, UART_LSR_OE, ch, flag); -ignore_char: - lsr = serial_in(up, UART_LSR); - } while ((lsr (UART_LSR_DR | UART_LSR_BI)) (max_count-- 0)); - spin_unlock(up-port.lock); - tty_flip_buffer_push(tty); - spin_lock(up-port.lock); -} - static void transmit_chars(struct uart_omap_port *up) { struct circ_buf *xmit = up-port.state-xmit; @@ -341,6 +273,68 @@ static unsigned int check_modem_status(struct uart_omap_port *up) return status; } +static void serial_omap_rlsi(struct uart_omap_port *up, unsigned int lsr) +{ + unsigned int flag; + + up-port.icount.rx++; + flag = TTY_NORMAL; + + if (lsr UART_LSR_BI) { + flag = TTY_BREAK; + lsr = ~(UART_LSR_FE | UART_LSR_PE); + up-port.icount.brk++; + /* +* We do the SysRQ and SAK checking +* here because otherwise the break +* may get masked by ignore_status_mask +* or read_status_mask. +*/ + if (uart_handle_break(up-port)) + return; + + } + + if (lsr UART_LSR_PE) { + flag = TTY_PARITY; + up-port.icount.parity++; + } + + if (lsr UART_LSR_FE) { + flag = TTY_FRAME; + up-port.icount.frame++; + } + + if (lsr UART_LSR_OE) + up-port.icount.overrun++; + +#ifdef CONFIG_SERIAL_OMAP_CONSOLE + if (up-port.line == up-port.cons-index) { + /* Recover the break flag from console xmit */ + lsr |= up-lsr_break_flag; + } +#endif + uart_insert_char(up-port, lsr, UART_LSR_OE, 0, flag); +} + +static void
[RFC/PATCH 04/13] serial: omap: don't access the platform_device
The driver doesn't need to know about its platform_device. Everything the driver needs can be done through the struct device pointer. In case we need to use the OMAP-specific PM function pointers, those can make sure to find the device's platform_device pointer so they can find the struct omap_device through pdev-archdata field. Signed-off-by: Felipe Balbi ba...@ti.com --- arch/arm/mach-omap2/serial.c | 15 ++-- arch/arm/plat-omap/include/plat/omap-serial.h | 10 +-- drivers/tty/serial/omap-serial.c | 124 +- 3 files changed, 76 insertions(+), 73 deletions(-) diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index c1b93c7..8f07841 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -81,8 +81,9 @@ static struct omap_uart_port_info omap_serial_default_info[] __initdata = { }; #ifdef CONFIG_PM -static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable) +static void omap_uart_enable_wakeup(struct device *dev, bool enable) { + struct platform_device *pdev = to_platform_device(dev); struct omap_device *od = to_omap_device(pdev); if (!od) @@ -99,15 +100,17 @@ static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable) * in Smartidle Mode When Configured for DMA Operations. * WA: configure uart in force idle mode. */ -static void omap_uart_set_noidle(struct platform_device *pdev) +static void omap_uart_set_noidle(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); struct omap_device *od = to_omap_device(pdev); omap_hwmod_set_slave_idlemode(od-hwmods[0], HWMOD_IDLEMODE_NO); } -static void omap_uart_set_smartidle(struct platform_device *pdev) +static void omap_uart_set_smartidle(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); struct omap_device *od = to_omap_device(pdev); u8 idlemode; @@ -120,10 +123,10 @@ static void omap_uart_set_smartidle(struct platform_device *pdev) } #else -static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable) +static void omap_uart_enable_wakeup(struct device *dev, bool enable) {} -static void omap_uart_set_noidle(struct platform_device *pdev) {} -static void omap_uart_set_smartidle(struct platform_device *pdev) {} +static void omap_uart_set_noidle(struct device *dev) {} +static void omap_uart_set_smartidle(struct device *dev) {} #endif /* CONFIG_PM */ #ifdef CONFIG_OMAP_MUX diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index f3b35d9..743ac80 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -18,7 +18,7 @@ #define __OMAP_SERIAL_H__ #include linux/serial_core.h -#include linux/platform_device.h +#include linux/device.h #include linux/pm_qos.h #include plat/mux.h @@ -71,9 +71,9 @@ struct omap_uart_port_info { unsigned intdma_rx_poll_rate; int (*get_context_loss_count)(struct device *); - void (*set_forceidle)(struct platform_device *); - void (*set_noidle)(struct platform_device *); - void (*enable_wakeup)(struct platform_device *, bool); + void (*set_forceidle)(struct device *); + void (*set_noidle)(struct device *); + void (*enable_wakeup)(struct device *, bool); }; struct uart_omap_dma { @@ -105,7 +105,7 @@ struct uart_omap_dma { struct uart_omap_port { struct uart_portport; struct uart_omap_dmauart_dma; - struct platform_device *pdev; + struct device *dev; unsigned char ier; unsigned char lcr; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index c3e6fa0..fb81366 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -103,36 +103,36 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up) static int serial_omap_get_context_loss_count(struct uart_omap_port *up) { - struct omap_uart_port_info *pdata = up-pdev-dev.platform_data; + struct omap_uart_port_info *pdata = up-dev-platform_data; if (!pdata-get_context_loss_count) return 0; - return pdata-get_context_loss_count(up-pdev-dev); + return pdata-get_context_loss_count(up-dev); } static void serial_omap_set_forceidle(struct uart_omap_port *up) { - struct omap_uart_port_info *pdata = up-pdev-dev.platform_data; + struct omap_uart_port_info *pdata = up-dev-platform_data; if (pdata-set_forceidle) - pdata-set_forceidle(up-pdev); + pdata-set_forceidle(up-dev); } static void serial_omap_set_noidle(struct uart_omap_port *up) { - struct omap_uart_port_info *pdata = up-pdev-dev.platform_data; + struct omap_uart_port_info *pdata
[RFC/PATCH 02/13] serial: omap: always return IRQ_HANDLED
Even if we enter our IRQ handler just to notice that the our device didn't generate the IRQ, that still means handling and IRQ, so let's return IRQ_HANDLED. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 5c0d0bc..b4b95fc 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -417,7 +417,7 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id) if (iir UART_IIR_NO_INT) { pm_runtime_mark_last_busy(up-pdev-dev); pm_runtime_put_autosuspend(up-pdev-dev); - return IRQ_NONE; + return IRQ_HANDLED; } spin_lock_irqsave(up-port.lock, flags); -- 1.7.12.rc3 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 00/10] Prepare for GPMC driver conversion (w.r.t MTD)
Hi, This is a RESEND of the series that was sent on 10-August-2012, which unfortunately did not make it to mailing lists. This series cleans up gpmc mtd interactions so that GPMC driver conversion which is going to happen shortly would happen smoothly by not creating much disturbance outside of arch/arm/*omap*/ This series, 1. provides the ability for OMAP NAND driver to configure GPMC-NAND registers by NAND driver itself instead of using exported GPMC symbols 2. modifies GPMC to provide OMAP ONENAND NAND drivers with GPMC allocated address space as resource 3. creates a fictitious GPMC interrupt chip and provide the clients with interrupts that could be handled using standard APIs (helps in removing the requirement for driver of peripheral connected to GPMC having the knowledge about GPMC interrupt handling). The only user is OMAP NAND driver, it has also been modified to take advantage of this This series has been made over linux-omap master can be applied over 3.6-rc1 too. This has been tested on omap3evm. Artem's Acked-by has been added to mtd patches except for 10/10 where a change has been made to handle error path properly. Regards Afzal v3: Handle error path properly v2: simplify omap_prefetch_enable() Afzal Mohammed (10): ARM: OMAP2+: gpmc: update nand register helper ARM: OMAP2+: gpmc-nand: update gpmc-nand regs mtd: nand: omap2: handle nand on gpmc ARM: OMAP2+: gpmc-nand: update resource with memory ARM: OMAP2+: gpmc-onenand: provide memory as resource mtd: nand: omap2: obtain memory from resource mtd: onenand: omap2: obtain memory from resource ARM: OMAP2+: gpmc: Modify interrupt handling ARM: OMAP2+: gpmc-nand: Modify Interrupt handling mtd: nand: omap2: use gpmc provided irqs arch/arm/mach-omap2/gpmc-nand.c| 28 +++- arch/arm/mach-omap2/gpmc-onenand.c | 23 +++- arch/arm/mach-omap2/gpmc.c | 156 +++-- arch/arm/plat-omap/include/plat/gpmc.h | 19 ++ arch/arm/plat-omap/include/plat/nand.h |2 +- drivers/mtd/nand/omap2.c | 299 drivers/mtd/onenand/omap2.c| 29 ++-- 7 files changed, 443 insertions(+), 113 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 01/10] ARM: OMAP2+: gpmc: update nand register helper
Provide helper function for updating NAND register details for the necessary chip select. NAND drivers platform data can be updated with this information so that NAND driver can handle GPMC NAND operations by itself. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 20 arch/arm/plat-omap/include/plat/gpmc.h | 18 ++ 2 files changed, 38 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index b2b5759..5cce9b0 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -682,6 +682,26 @@ int gpmc_prefetch_reset(int cs) } EXPORT_SYMBOL(gpmc_prefetch_reset); +void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) +{ + reg-gpmc_status = gpmc_base + GPMC_STATUS; + reg-gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET + + GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs; + reg-gpmc_nand_address = gpmc_base + GPMC_CS0_OFFSET + + GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs; + reg-gpmc_nand_data = gpmc_base + GPMC_CS0_OFFSET + + GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs; + reg-gpmc_prefetch_config1 = gpmc_base + GPMC_PREFETCH_CONFIG1; + reg-gpmc_prefetch_config2 = gpmc_base + GPMC_PREFETCH_CONFIG2; + reg-gpmc_prefetch_control = gpmc_base + GPMC_PREFETCH_CONTROL; + reg-gpmc_prefetch_status = gpmc_base + GPMC_PREFETCH_STATUS; + reg-gpmc_ecc_config = gpmc_base + GPMC_ECC_CONFIG; + reg-gpmc_ecc_control = gpmc_base + GPMC_ECC_CONTROL; + reg-gpmc_ecc_size_config = gpmc_base + GPMC_ECC_SIZE_CONFIG; + reg-gpmc_ecc1_result = gpmc_base + GPMC_ECC1_RESULT; + reg-gpmc_bch_result0 = gpmc_base + GPMC_ECC_BCH_RESULT_0; +} + static void __init gpmc_mem_init(void) { int cs; diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index f37764a..06198a5 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -133,6 +133,24 @@ struct gpmc_timings { u16 wr_data_mux_bus;/* WRDATAONADMUXBUS */ }; +struct gpmc_nand_regs { + void __iomem*gpmc_status; + void __iomem*gpmc_nand_command; + void __iomem*gpmc_nand_address; + void __iomem*gpmc_nand_data; + void __iomem*gpmc_prefetch_config1; + void __iomem*gpmc_prefetch_config2; + void __iomem*gpmc_prefetch_control; + void __iomem*gpmc_prefetch_status; + void __iomem*gpmc_ecc_config; + void __iomem*gpmc_ecc_control; + void __iomem*gpmc_ecc_size_config; + void __iomem*gpmc_ecc1_result; + void __iomem*gpmc_bch_result0; +}; + +extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); + extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns); extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps); extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/5] ARM: OMAP4: Add L2 Cache Controller in Device Tree
On Mon, Aug 20, 2012 at 9:21 PM, Shilimkar, Santosh santosh.shilim...@ti.com wrote: On Mon, Aug 20, 2012 at 7:21 PM, Benoit Cousson b-cous...@ti.com wrote: Hi Santosh, On 08/13/2012 01:00 PM, Santosh Shilimkar wrote: This provides PL310 Level 2 Cache Controller Device Tree support for OMAP4 based devices. Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Santosh Shilimkar santosh.shilim...@ti.com --- arch/arm/boot/dts/omap4.dtsi |7 +++ arch/arm/mach-omap2/omap4-common.c |6 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 6717c71..cf1efb6 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -36,6 +36,13 @@ }; }; + L2: l2-cache-controller { The reg offset is missing: l2-cache-controller@48242000 + compatible = arm,pl310-cache; + reg = 0x48242000 0x1000; + cache-unified; + cache-level = 2; + }; + In theory, the L2 cache should be referenced from the CPUs. Agree. I have added the reference for the L2 controller in CPUs. Other information like L1 cache size etc can be added in cpu DT node with another patch. Updated patch below. Have also updated git branch accordingly. Regards Santosh From 91d6cb4f999061c8cfc844a3916ee3384f2e488a Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar santosh.shilim...@ti.com Date: Wed, 4 Jul 2012 17:57:34 +0530 Subject: [PATCH 1/2 v2] ARM: OMAP4: Add L2 Cache Controller in Device Tree This provides PL310 Level 2 Cache Controller Device Tree support for OMAP4 based devices. Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Santosh Shilimkar santosh.shilim...@ti.com --- arch/arm/boot/dts/omap4.dtsi |9 + arch/arm/mach-omap2/omap4-common.c |6 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 6717c71..0229dd2 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -30,12 +30,21 @@ cpus { cpu@0 { compatible = arm,cortex-a9; + next-level-cache = L2; }; cpu@1 { compatible = arm,cortex-a9; + next-level-cache = L2; }; }; + L2: l2-cache-controller@48242000 { + compatible = arm,pl310-cache; + reg = 0x48242000 0x1000; + cache-unified; + cache-level = 2; + }; + /* * The soc node represents the soc top level view. It is uses for IPs * that are not memory mapped in the MPU view or for the MPU itself. diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index c29dee9..6f95992 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -16,6 +16,7 @@ #include linux/io.h #include linux/platform_device.h #include linux/memblock.h +#include linux/of.h #include asm/hardware/gic.h #include asm/hardware/cache-l2x0.h @@ -171,7 +172,10 @@ static int __init omap_l2_cache_init(void) /* Enable PL310 L2 Cache controller */ omap_smc1(0x102, 0x1); - l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK); + if (of_have_populated_dt()) + l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK); + else + l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK); /* * Override default outer_cache.disable with a OMAP4 -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 02/10] ARM: OMAP2+: gpmc-nand: update gpmc-nand regs
GPMC has NAND registers, update nand platform data with those details so that NAND driver can configure those by itself instead of using exported symbols. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-nand.c|2 ++ arch/arm/plat-omap/include/plat/nand.h |1 + 2 files changed, 3 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 386dec8..d4e803c 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -108,6 +108,8 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_RDY_BSY, 1); } + gpmc_update_nand_reg(gpmc_nand_data-reg, gpmc_nand_data-cs); + err = platform_device_register(gpmc_nand_device); if (err 0) { dev_err(dev, Unable to register NAND device\n); diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index 67fc506..86e4d9c 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -29,6 +29,7 @@ struct omap_nand_platform_data { unsigned long phys_base; int devsize; enum omap_ecc ecc_opt; + struct gpmc_nand_regs reg; }; /* minimum size for IO mapping */ -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 03/10] mtd: nand: omap2: handle nand on gpmc
GPMC platform initialization has been modified to fill NAND platform data with GPMC NAND register details. As these registers are accessible in NAND driver itself, configure NAND in GPMC by itself. Modified prefetch and ecc functions are logically same as the corresponding exported symbols from GPMC code. Note: Verfying that other CS have not yet enabled for prefetch ecc has to be incorporated. Currently this causes no issues as there are no boards that use NAND on multiple CS. With ongoing GPMC driver migration, perhaps it would be better to consider NAND connected on multiple CS as a single peripheral using multiple CS. This would make handling multiple CS issues easier. Signed-off-by: Afzal Mohammed af...@ti.com Acked-by: Artem Bityutskiy artem.bityuts...@linux.intel.com --- v2: simplify omap_prefetch_enable() drivers/mtd/nand/omap2.c | 206 -- 1 files changed, 161 insertions(+), 45 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index e9309b3..8ddca98 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -101,6 +101,16 @@ #define P4e_s(a) (TF(a NAND_Ecc_P4e)0) #define P4o_s(a) (TF(a NAND_Ecc_P4o)1) +#definePREFETCH_CONFIG1_CS_SHIFT 24 +#defineECC_CONFIG_CS_SHIFT 1 +#defineCS_MASK 0x7 +#defineENABLE_PREFETCH (0x1 7) +#defineDMA_MPU_MODE_SHIFT 2 +#defineECCSIZE1_SHIFT 22 +#defineECC1RESULTSIZE 0x1 +#defineECCCLEAR0x100 +#defineECC10x1 + /* oob info generated runtime depending on ecc algorithm and layout selected */ static struct nand_ecclayout omap_oobinfo; /* Define some generic bad / good block scan pattern which are used @@ -133,6 +143,7 @@ struct omap_nand_info { } iomode; u_char *buf; int buf_len; + struct gpmc_nand_regs reg; #ifdef CONFIG_MTD_NAND_OMAP_BCH struct bch_control *bch; @@ -141,6 +152,63 @@ struct omap_nand_info { }; /** + * omap_prefetch_enable - configures and starts prefetch transfer + * @cs: cs (chip select) number + * @fifo_th: fifo threshold to be used for read/ write + * @dma_mode: dma mode enable (1) or disable (0) + * @u32_count: number of bytes to be transferred + * @is_write: prefetch read(0) or write post(1) mode + */ +static int omap_prefetch_enable(int cs, int fifo_th, int dma_mode, + unsigned int u32_count, int is_write, struct omap_nand_info *info) +{ + u32 val; + + if (fifo_th PREFETCH_FIFOTHRESHOLD_MAX) + return -1; + + if (readl(info-reg.gpmc_prefetch_control)) + return -EBUSY; + + /* Set the amount of bytes to be prefetched */ + writel(u32_count, info-reg.gpmc_prefetch_config2); + + /* Set dma/mpu mode, the prefetch read / post write and +* enable the engine. Set which cs is has requested for. +*/ + val = ((cs PREFETCH_CONFIG1_CS_SHIFT) | + PREFETCH_FIFOTHRESHOLD(fifo_th) | ENABLE_PREFETCH | + (dma_mode DMA_MPU_MODE_SHIFT) | (0x1 is_write)); + writel(val, info-reg.gpmc_prefetch_config1); + + /* Start the prefetch engine */ + writel(0x1, info-reg.gpmc_prefetch_control); + + return 0; +} + +/** + * omap_prefetch_reset - disables and stops the prefetch engine + */ +static int omap_prefetch_reset(int cs, struct omap_nand_info *info) +{ + u32 config1; + + /* check if the same module/cs is trying to reset */ + config1 = readl(info-reg.gpmc_prefetch_config1); + if (((config1 PREFETCH_CONFIG1_CS_SHIFT) CS_MASK) != cs) + return -EINVAL; + + /* Stop the PFPW engine */ + writel(0x0, info-reg.gpmc_prefetch_control); + + /* Reset/disable the PFPW engine */ + writel(0x0, info-reg.gpmc_prefetch_config1); + + return 0; +} + +/** * omap_hwcontrol - hardware specific access to control-lines * @mtd: MTD device structure * @cmd: command to device @@ -158,13 +226,13 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) if (cmd != NAND_CMD_NONE) { if (ctrl NAND_CLE) - gpmc_nand_write(info-gpmc_cs, GPMC_NAND_COMMAND, cmd); + writeb(cmd, info-reg.gpmc_nand_command); else if (ctrl NAND_ALE) - gpmc_nand_write(info-gpmc_cs, GPMC_NAND_ADDRESS, cmd); + writeb(cmd, info-reg.gpmc_nand_address); else /* NAND_NCE */ - gpmc_nand_write(info-gpmc_cs, GPMC_NAND_DATA, cmd); + writeb(cmd, info-reg.gpmc_nand_data); } } @@ -198,7 +266,8 @@ static void
[PATCH v3 04/10] ARM: OMAP2+: gpmc-nand: update resource with memory
Currently omap nand driver uses a field in platform data - phys_base for passing the address space allocated by gpmc for nand. Use struct resource instead. With this change omap nand driver has to get address space from memory resource. This helps in smooth migration of gpmc to driver. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-nand.c |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index d4e803c..c0320d2 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -90,12 +90,14 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) gpmc_nand_device.dev.platform_data = gpmc_nand_data; err = gpmc_cs_request(gpmc_nand_data-cs, NAND_IO_SIZE, - gpmc_nand_data-phys_base); + (unsigned long *)gpmc_nand_resource.start); if (err 0) { dev_err(dev, Cannot request GPMC CS\n); return err; } + gpmc_nand_resource.end = gpmc_nand_resource.start + NAND_IO_SIZE - 1; + /* Set timings in GPMC */ err = omap2_nand_gpmc_retime(gpmc_nand_data); if (err 0) { -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 05/10] ARM: OMAP2+: gpmc-onenand: provide memory as resource
Currently omap onenand driver invokes gpmc_cs_request, obtains address space allocated by gpmc to onenand. Remove this, instead use resource structure; this is now updated with address space for onenand by gpmc initialization with the help of gpmc_cs_request. And remove usage of gpmc_cs_request in onenand driver. This helps in smooth migration of gpmc to driver. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-onenand.c | 23 ++- 1 files changed, 22 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index a0fa9bb..71d7c07 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -23,11 +23,19 @@ #include plat/board.h #include plat/gpmc.h +#defineONENAND_IO_SIZE SZ_128K + static struct omap_onenand_platform_data *gpmc_onenand_data; +static struct resource gpmc_onenand_resource = { + .flags = IORESOURCE_MEM, +}; + static struct platform_device gpmc_onenand_device = { .name = omap2-onenand, .id = -1, + .num_resources = 1, + .resource = gpmc_onenand_resource, }; static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) @@ -390,6 +398,8 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr) void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) { + int err; + gpmc_onenand_data = _onenand_data; gpmc_onenand_data-onenand_setup = gpmc_onenand_setup; gpmc_onenand_device.dev.platform_data = gpmc_onenand_data; @@ -401,8 +411,19 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) gpmc_onenand_data-flags |= ONENAND_SYNC_READ; } + err = gpmc_cs_request(gpmc_onenand_data-cs, ONENAND_IO_SIZE, + (unsigned long *)gpmc_onenand_resource.start); + if (err 0) { + pr_err(%s: Cannot request GPMC CS\n, __func__); + return; + } + + gpmc_onenand_resource.end = gpmc_onenand_resource.start + + ONENAND_IO_SIZE - 1; + if (platform_device_register(gpmc_onenand_device) 0) { - printk(KERN_ERR Unable to register OneNAND device\n); + pr_err(%s: Unable to register OneNAND device\n, __func__); + gpmc_cs_free(gpmc_onenand_data-cs); return; } } -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 06/10] mtd: nand: omap2: obtain memory from resource
gpmc initialization done by platform code now updates struct resource with the address space alloted for nand. Use this interface to obtain memory rather than relying on platform data field - phys_base. Signed-off-by: Afzal Mohammed af...@ti.com Acked-by: Artem Bityutskiy artem.bityuts...@linux.intel.com --- arch/arm/plat-omap/include/plat/nand.h |1 - drivers/mtd/nand/omap2.c | 19 +++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index 86e4d9c..290cef5 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -26,7 +26,6 @@ struct omap_nand_platform_data { booldev_ready; int gpmc_irq; enum nand_ioxfer_type; - unsigned long phys_base; int devsize; enum omap_ecc ecc_opt; struct gpmc_nand_regs reg; diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 8ddca98..f65f7f8 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -134,6 +134,7 @@ struct omap_nand_info { int gpmc_cs; unsigned long phys_base; + unsigned long mem_size; struct completion comp; struct dma_chan *dma; int gpmc_irq; @@ -1270,6 +1271,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) int i, offset; dma_cap_mask_t mask; unsigned sig; + struct resource *res; pdata = pdev-dev.platform_data; if (pdata == NULL) { @@ -1289,7 +1291,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info-pdev = pdev; info-gpmc_cs = pdata-cs; - info-phys_base = pdata-phys_base; info-reg = pdata-reg; info-mtd.priv = info-nand; @@ -1302,13 +1303,23 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) /* NAND write protect off */ gpmc_cs_configure(info-gpmc_cs, GPMC_CONFIG_WP, 0); - if (!request_mem_region(info-phys_base, NAND_IO_SIZE, + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + err = -EINVAL; + dev_err(pdev-dev, error getting memory resource\n); + goto out_free_info; + } + + info-phys_base = res-start; + info-mem_size = resource_size(res); + + if (!request_mem_region(info-phys_base, info-mem_size, pdev-dev.driver-name)) { err = -EBUSY; goto out_free_info; } - info-nand.IO_ADDR_R = ioremap(info-phys_base, NAND_IO_SIZE); + info-nand.IO_ADDR_R = ioremap(info-phys_base, info-mem_size); if (!info-nand.IO_ADDR_R) { err = -ENOMEM; goto out_release_mem_region; @@ -1480,7 +1491,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) out_release_mem_region: if (info-dma) dma_release_channel(info-dma); - release_mem_region(info-phys_base, NAND_IO_SIZE); + release_mem_region(info-phys_base, info-mem_size); out_free_info: kfree(info); -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 07/10] mtd: onenand: omap2: obtain memory from resource
gpmc initialization for onenand done by platform code now provides onenand address space as memory resource. Hence remove usage of gpmc_cs_request in onenand driver and obtain memory details from resource structure. Signed-off-by: Afzal Mohammed af...@ti.com Acked-by: Artem Bityutskiy artem.bityuts...@linux.intel.com --- drivers/mtd/onenand/omap2.c | 29 - 1 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 398a827..3ff893d 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -48,13 +48,13 @@ #define DRIVER_NAME omap2-onenand -#define ONENAND_IO_SIZESZ_128K #define ONENAND_BUFRAM_SIZE(1024 * 5) struct omap2_onenand { struct platform_device *pdev; int gpmc_cs; unsigned long phys_base; + unsigned int mem_size; int gpio_irq; struct mtd_info mtd; struct onenand_chip onenand; @@ -626,6 +626,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) struct omap2_onenand *c; struct onenand_chip *this; int r; + struct resource *res; pdata = pdev-dev.platform_data; if (pdata == NULL) { @@ -647,20 +648,24 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) c-gpio_irq = 0; } - r = gpmc_cs_request(c-gpmc_cs, ONENAND_IO_SIZE, c-phys_base); - if (r 0) { - dev_err(pdev-dev, Cannot request GPMC CS\n); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + r = -EINVAL; + dev_err(pdev-dev, error getting memory resource\n); goto err_kfree; } - if (request_mem_region(c-phys_base, ONENAND_IO_SIZE, + c-phys_base = res-start; + c-mem_size = resource_size(res); + + if (request_mem_region(c-phys_base, c-mem_size, pdev-dev.driver-name) == NULL) { - dev_err(pdev-dev, Cannot reserve memory region at 0x%08lx, - size: 0x%x\n, c-phys_base, ONENAND_IO_SIZE); + dev_err(pdev-dev, Cannot reserve memory region at 0x%08lx, size: 0x%x\n, + c-phys_base, c-mem_size); r = -EBUSY; - goto err_free_cs; + goto err_kfree; } - c-onenand.base = ioremap(c-phys_base, ONENAND_IO_SIZE); + c-onenand.base = ioremap(c-phys_base, c-mem_size); if (c-onenand.base == NULL) { r = -ENOMEM; goto err_release_mem_region; @@ -776,9 +781,7 @@ err_release_gpio: err_iounmap: iounmap(c-onenand.base); err_release_mem_region: - release_mem_region(c-phys_base, ONENAND_IO_SIZE); -err_free_cs: - gpmc_cs_free(c-gpmc_cs); + release_mem_region(c-phys_base, c-mem_size); err_kfree: kfree(c); @@ -800,7 +803,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev) gpio_free(c-gpio_irq); } iounmap(c-onenand.base); - release_mem_region(c-phys_base, ONENAND_IO_SIZE); + release_mem_region(c-phys_base, c-mem_size); gpmc_cs_free(c-gpmc_cs); kfree(c); -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 08/10] ARM: OMAP2+: gpmc: Modify interrupt handling
Modify interrupt handling such that interrupts can be handled by GPMC client drivers using standard interrupt APIs rather than requiring the drivers to have knowledge about GPMC interrupt handling. Currently only NAND related interrupts has been considered (which is the case even without this change) as the only user of GPMC interrupt is NAND. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 136 arch/arm/plat-omap/include/plat/gpmc.h |1 + 2 files changed, 120 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 5cce9b0..39c30d9 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -78,6 +78,15 @@ #define ENABLE_PREFETCH(0x1 7) #define DMA_MPU_MODE 2 +/* XXX: Only NAND irq has been considered,currently these are the only ones used + */ +#defineGPMC_NR_IRQ 2 + +struct gpmc_client_irq { + unsignedirq; + u32 bitmask; +}; + /* Structure to save gpmc cs context */ struct gpmc_cs_config { u32 config1; @@ -105,6 +114,10 @@ struct omap3_gpmc_regs { struct gpmc_cs_config cs_context[GPMC_CS_NUM]; }; +static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ]; +static struct irq_chip gpmc_irq_chip; +static unsigned gpmc_irq_start; + static struct resource gpmc_mem_root; static struct resource gpmc_cs_mem[GPMC_CS_NUM]; static DEFINE_SPINLOCK(gpmc_mem_lock); @@ -702,6 +715,97 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs) reg-gpmc_bch_result0 = gpmc_base + GPMC_ECC_BCH_RESULT_0; } +int gpmc_get_client_irq(unsigned irq_config) +{ + int i; + + if (hweight32(irq_config) 1) + return 0; + + for (i = 0; i GPMC_NR_IRQ; i++) + if (gpmc_client_irq[i].bitmask irq_config) + return gpmc_client_irq[i].irq; + + return 0; +} + +static int gpmc_irq_endis(unsigned irq, bool endis) +{ + int i; + u32 regval; + + for (i = 0; i GPMC_NR_IRQ; i++) + if (irq == gpmc_client_irq[i].irq) { + regval = gpmc_read_reg(GPMC_IRQENABLE); + if (endis) + regval |= gpmc_client_irq[i].bitmask; + else + regval = ~gpmc_client_irq[i].bitmask; + gpmc_write_reg(GPMC_IRQENABLE, regval); + break; + } + + return 0; +} + +static void gpmc_irq_disable(struct irq_data *p) +{ + gpmc_irq_endis(p-irq, false); +} + +static void gpmc_irq_enable(struct irq_data *p) +{ + gpmc_irq_endis(p-irq, true); +} + +static void gpmc_irq_noop(struct irq_data *data) { } + +static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; } + +static int gpmc_setup_irq(int gpmc_irq) +{ + int i; + u32 regval; + + if (!gpmc_irq) + return -EINVAL; + + gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0); + if (IS_ERR_VALUE(gpmc_irq_start)) { + pr_err(irq_alloc_descs failed\n); + return gpmc_irq_start; + } + + gpmc_irq_chip.name = gpmc; + gpmc_irq_chip.irq_startup = gpmc_irq_noop_ret; + gpmc_irq_chip.irq_enable = gpmc_irq_enable; + gpmc_irq_chip.irq_disable = gpmc_irq_disable; + gpmc_irq_chip.irq_shutdown = gpmc_irq_noop; + gpmc_irq_chip.irq_ack = gpmc_irq_noop; + gpmc_irq_chip.irq_mask = gpmc_irq_noop; + gpmc_irq_chip.irq_unmask = gpmc_irq_noop; + + gpmc_client_irq[0].bitmask = GPMC_IRQ_FIFOEVENTENABLE; + gpmc_client_irq[1].bitmask = GPMC_IRQ_COUNT_EVENT; + + for (i = 0; i GPMC_NR_IRQ; i++) { + gpmc_client_irq[i].irq = gpmc_irq_start + i; + irq_set_chip_and_handler(gpmc_client_irq[i].irq, + gpmc_irq_chip, handle_simple_irq); + set_irq_flags(gpmc_client_irq[i].irq, + IRQF_VALID | IRQF_NOAUTOEN); + } + + /* Disable interrupts */ + gpmc_write_reg(GPMC_IRQENABLE, 0); + + /* clear interrupts */ + regval = gpmc_read_reg(GPMC_IRQSTATUS); + gpmc_write_reg(GPMC_IRQSTATUS, regval); + + return request_irq(gpmc_irq, gpmc_handle_irq, 0, gpmc, NULL); +} + static void __init gpmc_mem_init(void) { int cs; @@ -731,8 +835,8 @@ static void __init gpmc_mem_init(void) static int __init gpmc_init(void) { - u32 l, irq; - int cs, ret = -EINVAL; + u32 l; + int ret = -EINVAL; int gpmc_irq; char *ck = NULL; @@ -781,16 +885,7 @@ static int __init gpmc_init(void) gpmc_write_reg(GPMC_SYSCONFIG, l); gpmc_mem_init(); - /* initalize the irq_chained */ - irq = OMAP_GPMC_IRQ_BASE; - for (cs = 0; cs GPMC_CS_NUM; cs++) { -
[PATCH v3 09/10] ARM: OMAP2+: gpmc-nand: Modify Interrupt handling
Now GPMC provides its client with interrupts that can be handled using the standard interrupt API. Modify GPMC NAND setup to work with it. Also disable write protect in GPMC code, so that NAND driver can be ignorant of GPMC configuration. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-nand.c | 26 -- 1 files changed, 20 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index c0320d2..045596a 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -21,15 +21,23 @@ #include plat/board.h #include plat/gpmc.h -static struct resource gpmc_nand_resource = { - .flags = IORESOURCE_MEM, +static struct resource gpmc_nand_resource[] = { + { + .flags = IORESOURCE_MEM, + }, + { + .flags = IORESOURCE_IRQ, + }, + { + .flags = IORESOURCE_IRQ, + }, }; static struct platform_device gpmc_nand_device = { .name = omap2-nand, .id = 0, - .num_resources = 1, - .resource = gpmc_nand_resource, + .num_resources = ARRAY_SIZE(gpmc_nand_resource), + .resource = gpmc_nand_resource, }; static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data) @@ -75,6 +83,7 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_DEV_SIZE, 0); gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND); + gpmc_cs_configure(gpmc_nand_data-cs, GPMC_CONFIG_WP, 0); err = gpmc_cs_set_timings(gpmc_nand_data-cs, t); if (err) return err; @@ -90,14 +99,19 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data) gpmc_nand_device.dev.platform_data = gpmc_nand_data; err = gpmc_cs_request(gpmc_nand_data-cs, NAND_IO_SIZE, - (unsigned long *)gpmc_nand_resource.start); + (unsigned long *)gpmc_nand_resource[0].start); if (err 0) { dev_err(dev, Cannot request GPMC CS\n); return err; } - gpmc_nand_resource.end = gpmc_nand_resource.start + NAND_IO_SIZE - 1; + gpmc_nand_resource[0].end = gpmc_nand_resource[0].start + + NAND_IO_SIZE - 1; + gpmc_nand_resource[1].start = + gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE); + gpmc_nand_resource[2].start = + gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); /* Set timings in GPMC */ err = omap2_nand_gpmc_retime(gpmc_nand_data); if (err 0) { -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 10/10] mtd: nand: omap2: use gpmc provided irqs
GPMC platform initialization provides it's clients with interrupts that can be used through struct resource. Make use of it for irq mode functionality. Also now write protect disable is done by GPMC, hence remove it. Signed-off-by: Afzal Mohammed af...@ti.com --- v3: Handle error path properly drivers/mtd/nand/omap2.c | 76 +- 1 files changed, 48 insertions(+), 28 deletions(-) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index f65f7f8..0e9d7b3 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -137,7 +137,8 @@ struct omap_nand_info { unsigned long mem_size; struct completion comp; struct dma_chan *dma; - int gpmc_irq; + int gpmc_irq_fifo; + int gpmc_irq_count; enum { OMAP_NAND_IO_READ = 0, /* read */ OMAP_NAND_IO_WRITE, /* write */ @@ -553,14 +554,12 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) { struct omap_nand_info *info = (struct omap_nand_info *) dev; u32 bytes; - u32 irq_stat; - irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS); bytes = readl(info-reg.gpmc_prefetch_status); bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes); bytes = bytes 0xFFFC; /* io in multiple of 4 bytes */ if (info-iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */ - if (irq_stat 0x2) + if (this_irq == info-gpmc_irq_count) goto done; if (info-buf_len (info-buf_len bytes)) @@ -577,20 +576,17 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev) (u32 *)info-buf, bytes 2); info-buf = info-buf + bytes; - if (irq_stat 0x2) + if (this_irq == info-gpmc_irq_count) goto done; } - gpmc_cs_configure(info-gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); return IRQ_HANDLED; done: complete(info-comp); - /* disable irq */ - gpmc_cs_configure(info-gpmc_cs, GPMC_ENABLE_IRQ, 0); - /* clear status */ - gpmc_cs_configure(info-gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); + disable_irq_nosync(info-gpmc_irq_fifo); + disable_irq_nosync(info-gpmc_irq_count); return IRQ_HANDLED; } @@ -624,9 +620,9 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len) goto out_copy; info-buf_len = len; - /* enable irq */ - gpmc_cs_configure(info-gpmc_cs, GPMC_ENABLE_IRQ, - (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); + + enable_irq(info-gpmc_irq_count); + enable_irq(info-gpmc_irq_fifo); /* waiting for read to complete */ wait_for_completion(info-comp); @@ -674,12 +670,13 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd, goto out_copy; info-buf_len = len; - /* enable irq */ - gpmc_cs_configure(info-gpmc_cs, GPMC_ENABLE_IRQ, - (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); + + enable_irq(info-gpmc_irq_count); + enable_irq(info-gpmc_irq_fifo); /* waiting for write to complete */ wait_for_completion(info-comp); + /* wait for data to flushed-out before reset the prefetch */ tim = 0; limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); @@ -1300,9 +1297,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info-nand.options = pdata-devsize; info-nand.options |= NAND_SKIP_BBTSCAN; - /* NAND write protect off */ - gpmc_cs_configure(info-gpmc_cs, GPMC_CONFIG_WP, 0); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { err = -EINVAL; @@ -1393,17 +1387,37 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) break; case NAND_OMAP_PREFETCH_IRQ: - err = request_irq(pdata-gpmc_irq, - omap_nand_irq, IRQF_SHARED, gpmc-nand, info); + info-gpmc_irq_fifo = platform_get_irq(pdev, 0); + if (info-gpmc_irq_fifo = 0) { + dev_err(pdev-dev, error getting fifo irq\n); + goto out_release_mem_region; + } + err = request_irq(info-gpmc_irq_fifo, omap_nand_irq, + IRQF_SHARED, gpmc-nand-fifo, info); if (err) { dev_err(pdev-dev, requesting irq(%d) error:%d, - pdata-gpmc_irq, err); + info-gpmc_irq_fifo, err); +
Re: [RFC/PATCH 05/13] serial: omap: drop DMA support
On Tue, Aug 21, 2012 at 2:45 PM, Felipe Balbi ba...@ti.com wrote: The current support is known to be broken and a later patch will come re-adding it using dma engine API. Signed-off-by: Felipe Balbi ba...@ti.com --- Thanks Felipe !! One less driver now towards OMAP DMA engine conversion. FWIW, Acked-by: Santosh Shilimkar santosh.shilim...@ti.com -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC/PATCH 05/13] serial: omap: drop DMA support
On Tue, Aug 21, 2012 at 03:14:19PM +0530, Shilimkar, Santosh wrote: On Tue, Aug 21, 2012 at 2:45 PM, Felipe Balbi ba...@ti.com wrote: The current support is known to be broken and a later patch will come re-adding it using dma engine API. Signed-off-by: Felipe Balbi ba...@ti.com --- Thanks Felipe !! no problem. One less driver now towards OMAP DMA engine conversion. indeed :-) I'll take a closer look into rx timeout IRQ, but it looks like we can use it to kick dma only for big transfers... need to play with it for a while first, though. FWIW, Acked-by: Santosh Shilimkar santosh.shilim...@ti.com is this Ack for this patch only or the entire series ?? -- balbi signature.asc Description: Digital signature
Re: [PATCH 4/5] ARM: OMAP4: Add L2 Cache Controller in Device Tree
On Tue, Aug 21, 2012 at 03:11:51PM +0530, Shilimkar, Santosh wrote: On Mon, Aug 20, 2012 at 9:21 PM, Shilimkar, Santosh santosh.shilim...@ti.com wrote: On Mon, Aug 20, 2012 at 7:21 PM, Benoit Cousson b-cous...@ti.com wrote: Hi Santosh, On 08/13/2012 01:00 PM, Santosh Shilimkar wrote: This provides PL310 Level 2 Cache Controller Device Tree support for OMAP4 based devices. Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Santosh Shilimkar santosh.shilim...@ti.com --- arch/arm/boot/dts/omap4.dtsi |7 +++ arch/arm/mach-omap2/omap4-common.c |6 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 6717c71..cf1efb6 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -36,6 +36,13 @@ }; }; + L2: l2-cache-controller { The reg offset is missing: l2-cache-controller@48242000 + compatible = arm,pl310-cache; + reg = 0x48242000 0x1000; + cache-unified; + cache-level = 2; + }; + In theory, the L2 cache should be referenced from the CPUs. Agree. I have added the reference for the L2 controller in CPUs. Other information like L1 cache size etc can be added in cpu DT node with another patch. Updated patch below. Have also updated git branch accordingly. Regards Santosh From 91d6cb4f999061c8cfc844a3916ee3384f2e488a Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar santosh.shilim...@ti.com Date: Wed, 4 Jul 2012 17:57:34 +0530 Subject: [PATCH 1/2 v2] ARM: OMAP4: Add L2 Cache Controller in Device Tree This provides PL310 Level 2 Cache Controller Device Tree support for OMAP4 based devices. Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Santosh Shilimkar santosh.shilim...@ti.com nice work :-) FWIW this looks good to me: Acked-by: Felipe Balbi ba...@ti.com just one thing, will a similar patch for omap3 be sent ? cheers --- arch/arm/boot/dts/omap4.dtsi |9 + arch/arm/mach-omap2/omap4-common.c |6 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 6717c71..0229dd2 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -30,12 +30,21 @@ cpus { cpu@0 { compatible = arm,cortex-a9; + next-level-cache = L2; }; cpu@1 { compatible = arm,cortex-a9; + next-level-cache = L2; }; }; + L2: l2-cache-controller@48242000 { + compatible = arm,pl310-cache; + reg = 0x48242000 0x1000; + cache-unified; + cache-level = 2; + }; + /* * The soc node represents the soc top level view. It is uses for IPs * that are not memory mapped in the MPU view or for the MPU itself. diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index c29dee9..6f95992 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -16,6 +16,7 @@ #include linux/io.h #include linux/platform_device.h #include linux/memblock.h +#include linux/of.h #include asm/hardware/gic.h #include asm/hardware/cache-l2x0.h @@ -171,7 +172,10 @@ static int __init omap_l2_cache_init(void) /* Enable PL310 L2 Cache controller */ omap_smc1(0x102, 0x1); - l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK); + if (of_have_populated_dt()) + l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK); + else + l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK); /* * Override default outer_cache.disable with a OMAP4 -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- balbi signature.asc Description: Digital signature
Re: [PATCH V5 1/6] OMAPDSS: DISPC: cleanup cpu_is_xxxx checks
On Mon, 2012-08-20 at 18:52 +0530, Chandrabhanu Mahapatra wrote: All the cpu_is checks have been moved to dispc_init_features function providing a much more generic and cleaner interface. The OMAP version and revision specific functions and data are initialized by dispc_features structure which is local to dispc.c. Signed-off-by: Chandrabhanu Mahapatra cmahapa...@ti.com --- drivers/video/omap2/dss/dispc.c | 433 +-- 1 file changed, 278 insertions(+), 155 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index ff52702..3fad33a 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -81,6 +81,23 @@ struct dispc_irq_stats { unsigned irqs[32]; }; +struct dispc_features { + int hp_max; + int vp_max; + int sw_max; + int sw_start; + int fp_start; + int bp_start; Here you could use a bit smaller datatype. u16 should probably be more than enough. +static int __init dispc_init_features(struct device *dev) +{ + struct dispc_features *feat = devm_kzalloc(dev, sizeof(*feat), + GFP_KERNEL); + if (!feat) { + dev_err(dev, Failed to allocate DISPC Features\n); + return -ENOMEM; + } + + if (cpu_is_omap24xx()) { + memcpy(feat, omap24xx_dispc_feats, sizeof(*feat)); + } else if (cpu_is_omap34xx()) { + if (omap_rev() OMAP3430_REV_ES3_0) + memcpy(feat, omap34xx_rev1_0_dispc_feats, + sizeof(*feat)); + else + memcpy(feat, omap34xx_rev3_0_dispc_feats, + sizeof(*feat)); + } else if (cpu_is_omap44xx()) { + memcpy(feat, omap44xx_dispc_feats, sizeof(*feat)); + } else { + return -ENODEV; + } + + dispc.feat = feat; + + return 0; +} This becomes much cleaner with something like the following (same could be used in dss.c also): const struct dispc_features *src; struct dispc_features *dst; dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL); if (!dsst) { dev_err(dev, Failed to allocate DISPC Features\n); return -ENOMEM; } if (cpu_is_omap24xx()) { src = omap24xx_dispc_feats; } else if (cpu_is_omap34xx()) { if (omap_rev() OMAP3430_REV_ES3_0) src = omap34xx_rev1_0_dispc_feats; else src = omap34xx_rev3_0_dispc_feats; } else if (cpu_is_omap44xx()) { src = omap44xx_dispc_feats; } else { return -ENODEV; } memcpy(dst, src, sizeof(*dst)); dispc.feat = dst; Tomi signature.asc Description: This is a digitally signed message part
Re: [PATCH V5 5/6] ARM: OMAP: Disable venc for OMAP4
On Mon, 2012-08-20 at 18:54 +0530, Chandrabhanu Mahapatra wrote: This is a alternative to HACK: OMAP: DSS2: VENC: disable VENC on OMAP4 to prevent crash (ba02fa37de) by Tomi Valkeinen tomi.valkei...@ti.com to prevent VENC from crashing OMAP4 kernel. This prevents OMAPDSS from initial registration of a device for VENC on OMAP4. Signed-off-by: Chandrabhanu Mahapatra cmahapa...@ti.com --- arch/arm/mach-omap2/display.c |1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index af1ed7d..ee40739 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -95,7 +95,6 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = { { dss_core, omapdss_dss, -1 }, { dss_dispc, omapdss_dispc, -1 }, { dss_rfbi, omapdss_rfbi, -1 }, - { dss_venc, omapdss_venc, -1 }, { dss_dsi1, omapdss_dsi, 0 }, { dss_dsi2, omapdss_dsi, 1 }, { dss_hdmi, omapdss_hdmi, -1 }, You need to reorder this and the previous patch. If you first remove the workaround from the previous patch, the kernel will crash if after that patch. So this one should be before the previous patch. Tomi signature.asc Description: This is a digitally signed message part
Re: [PATCH 4/5] ARM: OMAP4: Add L2 Cache Controller in Device Tree
On Tue, Aug 21, 2012 at 3:54 PM, Felipe Balbi ba...@ti.com wrote: On Tue, Aug 21, 2012 at 03:11:51PM +0530, Shilimkar, Santosh wrote: On Mon, Aug 20, 2012 at 9:21 PM, Shilimkar, Santosh santosh.shilim...@ti.com wrote: On Mon, Aug 20, 2012 at 7:21 PM, Benoit Cousson b-cous...@ti.com wrote: Hi Santosh, On 08/13/2012 01:00 PM, Santosh Shilimkar wrote: This provides PL310 Level 2 Cache Controller Device Tree support for OMAP4 based devices. Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Santosh Shilimkar santosh.shilim...@ti.com --- arch/arm/boot/dts/omap4.dtsi |7 +++ arch/arm/mach-omap2/omap4-common.c |6 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 6717c71..cf1efb6 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -36,6 +36,13 @@ }; }; + L2: l2-cache-controller { The reg offset is missing: l2-cache-controller@48242000 + compatible = arm,pl310-cache; + reg = 0x48242000 0x1000; + cache-unified; + cache-level = 2; + }; + In theory, the L2 cache should be referenced from the CPUs. Agree. I have added the reference for the L2 controller in CPUs. Other information like L1 cache size etc can be added in cpu DT node with another patch. Updated patch below. Have also updated git branch accordingly. Regards Santosh From 91d6cb4f999061c8cfc844a3916ee3384f2e488a Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar santosh.shilim...@ti.com Date: Wed, 4 Jul 2012 17:57:34 +0530 Subject: [PATCH 1/2 v2] ARM: OMAP4: Add L2 Cache Controller in Device Tree This provides PL310 Level 2 Cache Controller Device Tree support for OMAP4 based devices. Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Santosh Shilimkar santosh.shilim...@ti.com nice work :-) FWIW this looks good to me: Acked-by: Felipe Balbi ba...@ti.com Thanks. just one thing, will a similar patch for omap3 be sent ? OMAP3 has an integrated L2 cache controller so there won't any additional DT node for L2. OMAP3 CPU DT node can be updated with l1/l2 cache size etc related information though. Regards Santosh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/5] ARM: OMAP4: Add L2 Cache Controller in Device Tree
On Tue, Aug 21, 2012 at 04:02:38PM +0530, Shilimkar, Santosh wrote: On Tue, Aug 21, 2012 at 3:54 PM, Felipe Balbi ba...@ti.com wrote: On Tue, Aug 21, 2012 at 03:11:51PM +0530, Shilimkar, Santosh wrote: On Mon, Aug 20, 2012 at 9:21 PM, Shilimkar, Santosh santosh.shilim...@ti.com wrote: On Mon, Aug 20, 2012 at 7:21 PM, Benoit Cousson b-cous...@ti.com wrote: Hi Santosh, On 08/13/2012 01:00 PM, Santosh Shilimkar wrote: This provides PL310 Level 2 Cache Controller Device Tree support for OMAP4 based devices. Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Santosh Shilimkar santosh.shilim...@ti.com --- arch/arm/boot/dts/omap4.dtsi |7 +++ arch/arm/mach-omap2/omap4-common.c |6 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 6717c71..cf1efb6 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -36,6 +36,13 @@ }; }; + L2: l2-cache-controller { The reg offset is missing: l2-cache-controller@48242000 + compatible = arm,pl310-cache; + reg = 0x48242000 0x1000; + cache-unified; + cache-level = 2; + }; + In theory, the L2 cache should be referenced from the CPUs. Agree. I have added the reference for the L2 controller in CPUs. Other information like L1 cache size etc can be added in cpu DT node with another patch. Updated patch below. Have also updated git branch accordingly. Regards Santosh From 91d6cb4f999061c8cfc844a3916ee3384f2e488a Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar santosh.shilim...@ti.com Date: Wed, 4 Jul 2012 17:57:34 +0530 Subject: [PATCH 1/2 v2] ARM: OMAP4: Add L2 Cache Controller in Device Tree This provides PL310 Level 2 Cache Controller Device Tree support for OMAP4 based devices. Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Santosh Shilimkar santosh.shilim...@ti.com nice work :-) FWIW this looks good to me: Acked-by: Felipe Balbi ba...@ti.com Thanks. just one thing, will a similar patch for omap3 be sent ? OMAP3 has an integrated L2 cache controller so there won't any additional DT node for L2. OMAP3 CPU DT node can be updated with l1/l2 cache size etc related information though. fair enough, thanks for the info. -- balbi signature.asc Description: Digital signature
Re: [PATCH V5 3/6] OMAPDSS: DSS: Cleanup cpu_is_xxxx checks
On Mon, 2012-08-20 at 18:53 +0530, Chandrabhanu Mahapatra wrote: All the cpu_is checks have been moved to dss_init_features function providing a much more generic and cleaner interface. The OMAP version and revision specific initializations in various functions are cleaned and the necessary data are moved to dss_features structure which is local to dss.c. Signed-off-by: Chandrabhanu Mahapatra cmahapa...@ti.com --- drivers/video/omap2/dss/dss.c | 117 ++--- 1 file changed, 76 insertions(+), 41 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 10566ae..f6d3d0a 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -31,6 +31,7 @@ #include linux/clk.h #include linux/platform_device.h #include linux/pm_runtime.h +#include linux/gfp.h #include video/omapdss.h @@ -65,6 +66,12 @@ struct dss_reg { static int dss_runtime_get(void); static void dss_runtime_put(void); +struct dss_features { + u16 fck_div_max; + int dss_fck_multiplier; + char *clk_name; const char * Tomi signature.asc Description: This is a digitally signed message part
Re: [RFC/PATCH 05/13] serial: omap: drop DMA support
On Tue, Aug 21, 2012 at 3:50 PM, Felipe Balbi ba...@ti.com wrote: On Tue, Aug 21, 2012 at 03:14:19PM +0530, Shilimkar, Santosh wrote: On Tue, Aug 21, 2012 at 2:45 PM, Felipe Balbi ba...@ti.com wrote: The current support is known to be broken and a later patch will come re-adding it using dma engine API. Signed-off-by: Felipe Balbi ba...@ti.com --- Thanks Felipe !! no problem. One less driver now towards OMAP DMA engine conversion. indeed :-) I'll take a closer look into rx timeout IRQ, but it looks like we can use it to kick dma only for big transfers... need to play with it for a while first, though. Yep. The RX path with DMA is bit of difficult part to manage for UART. FWIW, Acked-by: Santosh Shilimkar santosh.shilim...@ti.com is this Ack for this patch only or the entire series ?? Two more patches to review and then I will do it for full series on top of the cover-letter :-) Regards Santosh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC/PATCH 05/13] serial: omap: drop DMA support
On Tue, Aug 21, 2012 at 04:05:22PM +0530, Shilimkar, Santosh wrote: On Tue, Aug 21, 2012 at 3:50 PM, Felipe Balbi ba...@ti.com wrote: On Tue, Aug 21, 2012 at 03:14:19PM +0530, Shilimkar, Santosh wrote: On Tue, Aug 21, 2012 at 2:45 PM, Felipe Balbi ba...@ti.com wrote: The current support is known to be broken and a later patch will come re-adding it using dma engine API. Signed-off-by: Felipe Balbi ba...@ti.com --- Thanks Felipe !! no problem. One less driver now towards OMAP DMA engine conversion. indeed :-) I'll take a closer look into rx timeout IRQ, but it looks like we can use it to kick dma only for big transfers... need to play with it for a while first, though. Yep. The RX path with DMA is bit of difficult part to manage for UART. FWIW, Acked-by: Santosh Shilimkar santosh.shilim...@ti.com is this Ack for this patch only or the entire series ?? Two more patches to review and then I will do it for full series on top of the cover-letter :-) cool, thanks -- balbi signature.asc Description: Digital signature
Re: [PATCH v2] OMAPDSS: Do not require a VDDS_DSI regulator on am35xx
Hi, On Wed, 2012-08-15 at 15:16 -0400, Raphael Assenat wrote: On our AM3505 based board, dpi.c complains that there is no VDSS_DSI regulator and the framebuffer cannot be enabled. However, this check does not seem to apply to AM3505/17 chips. Taking into account comments received after my first patch[1], I have added entries to dss_features.c to support the am35xx soc. Then in dpi.c, instead of using cpu_is_omap34xx() and soc_is_am35xx(), a call to dss_has_feature() is used. [1] http://marc.info/?l=linux-fbdevm=134272967203409w=2 Signed-off-by: Raphaël Assénat r...@8d.com Chandrabhanu has posted a series that removes a bunch of cpu_is checks from omapdss. On of them is the use of VDDS_DSI in dpi.c. Can you wait until I've merged those patches to omapdss master branch (probably a few days), and then create a new patch that adds AM35xx to dss_features? Tomi signature.asc Description: This is a digitally signed message part
Re: [RFC/PATCH 10/13] serial: omap: stick to put_autosuspend
On Tue, Aug 21, 2012 at 2:45 PM, Felipe Balbi ba...@ti.com wrote: Everytime we're done using our TTY, we want the pm timer to be reinitilized. By sticking to pm_runtime_pm_autosuspend() we make sure that this will always be the case. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 33 ++--- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 6ea24c5..458d77c 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -164,7 +164,8 @@ static void serial_omap_enable_ms(struct uart_port *port) pm_runtime_get_sync(up-dev); up-ier |= UART_IER_MSI; serial_out(up, UART_IER, up-ier); - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); } Can you please expand the change-log a bit ? Didn't follow the time re-init part completely. Regards Santosh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/5] ARM: OMAP4: Add L2 Cache Controller in Device Tree
Hi Santosh, On 08/21/2012 12:32 PM, Shilimkar, Santosh wrote: On Tue, Aug 21, 2012 at 3:54 PM, Felipe Balbi ba...@ti.com wrote: On Tue, Aug 21, 2012 at 03:11:51PM +0530, Shilimkar, Santosh wrote: On Mon, Aug 20, 2012 at 9:21 PM, Shilimkar, Santosh santosh.shilim...@ti.com wrote: On Mon, Aug 20, 2012 at 7:21 PM, Benoit Cousson b-cous...@ti.com wrote: Hi Santosh, On 08/13/2012 01:00 PM, Santosh Shilimkar wrote: This provides PL310 Level 2 Cache Controller Device Tree support for OMAP4 based devices. Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Santosh Shilimkar santosh.shilim...@ti.com --- arch/arm/boot/dts/omap4.dtsi |7 +++ arch/arm/mach-omap2/omap4-common.c |6 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 6717c71..cf1efb6 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -36,6 +36,13 @@ }; }; + L2: l2-cache-controller { The reg offset is missing: l2-cache-controller@48242000 + compatible = arm,pl310-cache; + reg = 0x48242000 0x1000; + cache-unified; + cache-level = 2; + }; + In theory, the L2 cache should be referenced from the CPUs. Agree. I have added the reference for the L2 controller in CPUs. Other information like L1 cache size etc can be added in cpu DT node with another patch. Updated patch below. Have also updated git branch accordingly. Regards Santosh From 91d6cb4f999061c8cfc844a3916ee3384f2e488a Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar santosh.shilim...@ti.com Date: Wed, 4 Jul 2012 17:57:34 +0530 Subject: [PATCH 1/2 v2] ARM: OMAP4: Add L2 Cache Controller in Device Tree This provides PL310 Level 2 Cache Controller Device Tree support for OMAP4 based devices. Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Santosh Shilimkar santosh.shilim...@ti.com nice work :-) FWIW this looks good to me: Acked-by: Felipe Balbi ba...@ti.com Thanks. just one thing, will a similar patch for omap3 be sent ? OMAP3 has an integrated L2 cache controller so there won't any additional DT node for L2. OMAP3 CPU DT node can be updated with l1/l2 cache size etc related information though. That's not needed if the information is available from the HW. DT is only there to provide information that cannot be extracted from HW. If CP15 registers already contains the details about caches, then there is no need to add them in the DT file. Regards, Benoit -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC/PATCH 00/13] OMAP UART patches
On Tue, Aug 21, 2012 at 2:45 PM, Felipe Balbi ba...@ti.com wrote: Hi guys, here's a series of cleanup patches to the OMAP serial driver. A later series could be made re-implementing DMA using the DMA Engine API. Note that for RX DMA we could be using RX Timeout IRQ as a hint that we better use PIO instead ;-) All patches were tested on my pandaboard, but I'd really like to receive Tested-by on other platforms. After this goes in, I'll probably try to get UART wakeup working again and only after that look at DMA. cheers Felipe Balbi (13): serial: omap: define and use to_uart_omap_port() serial: omap: always return IRQ_HANDLED serial: omap: define helpers for pdata function pointers serial: omap: don't access the platform_device serial: omap: drop DMA support serial: add OMAP-specific defines serial: omap: simplify IRQ handling serial: omap: refactor receive_chars() into rdi/rlsi handlers serial: omap: move THRE check to transmit_chars() serial: omap: stick to put_autosuspend serial: omap: set dev-drvdata before enabling pm_runtime serial: omap: drop unnecessary check from remove serial: omap: make sure to suspend device before remove Apart from that one question on last patch, rest of the clean-up is really good. Nice work. FWIW, Acked-by: Santosh Shilimkar santosh.shilim...@ti.com -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 02/10] ARM: OMAP2+: gpmc: handle additional timings
Configure busturnaround, cycle2cycledelay, waitmonitoringtime, clkactivationtime in gpmc_cs_set_timings(). This is done so that boards can configure these parameters of gpmc in Kernel instead of relying on bootloader. Also configure bool type timings like extradelay. This needed change to the existing users that were configuring clk activation time and extra delay by directly writing to registers. Thanks to Tony for making me aware of users of clk activation and being kind enough to test the modified one. Signed-off-by: Afzal Mohammed af...@ti.com --- v6: Move extra delay time user handling to present one from 3/10 v3: Handle bool type timings too v2: Make use of timing api for setting clock activation time, and remove direct writing to register for clock activation. arch/arm/mach-omap2/gpmc-onenand.c | 28 --- arch/arm/mach-omap2/gpmc.c | 45 arch/arm/mach-omap2/usb-tusb6010.c |3 +- arch/arm/plat-omap/include/plat/gpmc.h | 19 + 4 files changed, 72 insertions(+), 23 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 71d7c07..977b71d 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -284,27 +284,10 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, sync_read, sync_write, hf, vhf); if (div == 1) { - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); - reg |= (1 7); - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); - reg |= (1 7); - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); - reg |= (1 7); - reg |= (1 23); - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); - } else { - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); - reg = ~(1 7); - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); - reg = ~(1 7); - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); - reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); - reg = ~(1 7); - reg = ~(1 23); - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); + t.bool_timings.cs_extra_delay = true; + t.bool_timings.adv_extra_delay = true; + t.bool_timings.oe_extra_delay = true; + t.bool_timings.we_extra_delay = true; } /* Set synchronous read timings */ @@ -329,6 +312,8 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div + ticks_cez); + t.clk_activation = fclk_offset_ns; + /* Write */ if (sync_write) { t.adv_wr_off = t.adv_rd_off; @@ -362,7 +347,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | - GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | GPMC_CONFIG1_PAGE_LEN(2) | (cpu_is_omap34xx() ? 0 : (GPMC_CONFIG1_WAIT_READ_MON | diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 39c30d9..070fac5 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -64,6 +64,13 @@ #define GPMC_ECC_CTRL_ECCREG8 0x008 #define GPMC_ECC_CTRL_ECCREG9 0x009 +#defineGPMC_CONFIG2_CSEXTRADELAY BIT(7) +#defineGPMC_CONFIG3_ADVEXTRADELAY BIT(7) +#defineGPMC_CONFIG4_OEEXTRADELAY BIT(7) +#defineGPMC_CONFIG4_WEEXTRADELAY BIT(23) +#defineGPMC_CONFIG6_CYCLE2CYCLEDIFFCSENBIT(6) +#defineGPMC_CONFIG6_CYCLE2CYCLESAMECSENBIT(7) + #define GPMC_CS0_OFFSET0x60 #define GPMC_CS_SIZE 0x30 @@ -220,6 +227,36 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) return ticks * gpmc_get_fclk_period() / 1000; } +static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value) +{ + u32 l; + + l = gpmc_cs_read_reg(cs, reg); + if (value) + l |= mask; + else + l = ~mask; + gpmc_cs_write_reg(cs, reg, l); +} + +static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) +{ + gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1, +
[PATCH v6 01/10] ARM: OMAP2+: nand: unify init functions
Helper function for updating nand platform data has been added the capability to take timing structure arguement. Usage of omap_nand_flash_init() has been replaced by modifed one, omap_nand_flash_init was doing things similar to board_nand_init except that NAND CS# were being acquired based on bootloader setting. As CS# is hardwired for a given board, acquiring gpmc CS# has been removed, and updated with the value on board. NAND CS# used in beagle board omap3evm was found to be CS0. Thomas Weber thomas.weber.li...@googlemail.com reported that value of devkit8000 to be CS0. Overo board was found to be using CS0 based on u-boot, while google grep says omap3touchbook too has CS0. Signed-off-by: Afzal Mohammed af...@ti.com Reviewed-by: Jon Hunter jon-hun...@ti.com --- v6: Modify nand init for OMAP3EVM too as support got added arch/arm/mach-omap2/board-devkit8000.c |8 - arch/arm/mach-omap2/board-flash.c | 45 ++- arch/arm/mach-omap2/board-flash.h |6 ++- arch/arm/mach-omap2/board-igep0020.c |2 +- arch/arm/mach-omap2/board-ldp.c|4 +- arch/arm/mach-omap2/board-omap3beagle.c|8 - arch/arm/mach-omap2/board-omap3evm.c |8 - arch/arm/mach-omap2/board-omap3touchbook.c |8 - arch/arm/mach-omap2/board-overo.c |7 +++- arch/arm/mach-omap2/board-zoom.c |5 ++- arch/arm/mach-omap2/common-board-devices.c | 46 arch/arm/mach-omap2/common-board-devices.h |1 - 12 files changed, 62 insertions(+), 86 deletions(-) diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 6567c1c..6ee429a 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -59,8 +59,11 @@ #include mux.h #include hsmmc.h +#include board-flash.h #include common-board-devices.h +#defineNAND_CS 0 + #define OMAP_DM9000_GPIO_IRQ 25 #define OMAP3_DEVKIT_TS_GPIO 27 @@ -628,8 +631,9 @@ static void __init devkit8000_init(void) usb_musb_init(NULL); usbhs_init(usbhs_bdata); - omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, -ARRAY_SIZE(devkit8000_nand_partitions)); + board_nand_init(devkit8000_nand_partitions, + ARRAY_SIZE(devkit8000_nand_partitions), NAND_CS, + NAND_BUSWIDTH_16, NULL); /* Ensure SDRC pins are mux'd for self-refresh */ omap_mux_init_signal(sdrc_cke0, OMAP_PIN_OUTPUT); diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 53c39d2..47fb903 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -103,41 +103,41 @@ __init board_onenand_init(struct mtd_partition *onenand_parts, defined(CONFIG_MTD_NAND_OMAP2_MODULE) /* Note that all values in this struct are in nanoseconds */ -static struct gpmc_timings nand_timings = { +struct gpmc_timings nand_default_timings[1] = { + { + .sync_clk = 0, - .sync_clk = 0, + .cs_on = 0, + .cs_rd_off = 36, + .cs_wr_off = 36, - .cs_on = 0, - .cs_rd_off = 36, - .cs_wr_off = 36, + .adv_on = 6, + .adv_rd_off = 24, + .adv_wr_off = 36, - .adv_on = 6, - .adv_rd_off = 24, - .adv_wr_off = 36, + .we_off = 30, + .oe_off = 48, - .we_off = 30, - .oe_off = 48, + .access = 54, + .rd_cycle = 72, + .wr_cycle = 72, - .access = 54, - .rd_cycle = 72, - .wr_cycle = 72, - - .wr_access = 30, - .wr_data_mux_bus = 0, + .wr_access = 30, + .wr_data_mux_bus = 0, + }, }; -static struct omap_nand_platform_data board_nand_data = { - .gpmc_t = nand_timings, -}; +static struct omap_nand_platform_data board_nand_data; void -__init board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs, int nand_type) +__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, + int nand_type, struct gpmc_timings *gpmc_t) { board_nand_data.cs = cs; board_nand_data.parts = nand_parts; board_nand_data.nr_parts= nr_parts; board_nand_data.devsize = nand_type; + board_nand_data.gpmc_t = gpmc_t; board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs; @@ -238,5 +238,6 @@ void __init board_flash_init(struct flash_partitions partition_info[], pr_err(NAND: Unable to find configuration in GPMC\n); else board_nand_init(partition_info[2].parts, -
[PATCH v6 03/10] ARM: OMAP2+: onenand: refactor for clarity
Refactor set_async_mode set_sync_mode functions to separate out timing calculation actual configuration (GPMC OneNAND side). Thanks to Jon for his suggestions. Signed-off-by: Afzal Mohammed af...@ti.com Reviewed-by: Jon Hunter jon-hun...@ti.com --- v6: 1. Set OneNAND part to async mode before gpmc configuration 2. Move extra delay time user handling away from this patch (3/10 - 2/10) v5: Use flags for sync_read/write, hv, vhf v4: Reorganize OneNAND set_sync/async functions in a better way v3: Refactor OneNAND set_sync/async functions to separate out timing and configurations v2: Move ensuring that async mode in OneNAND has been setup from set_sync to setup function, improve commit message arch/arm/mach-omap2/gpmc-onenand.c | 174 ++- 1 files changed, 109 insertions(+), 65 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 977b71d..bbae674 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -15,6 +15,7 @@ #include linux/platform_device.h #include linux/mtd/onenand_regs.h #include linux/io.h +#include linux/err.h #include asm/mach/flash.h @@ -25,6 +26,14 @@ #defineONENAND_IO_SIZE SZ_128K +#defineONENAND_FLAG_SYNCREAD (1 0) +#defineONENAND_FLAG_SYNCWRITE (1 1) +#defineONENAND_FLAG_HF (1 2) +#defineONENAND_FLAG_VHF(1 3) + +static unsigned onenand_flags; +static unsigned latency; + static struct omap_onenand_platform_data *gpmc_onenand_data; static struct resource gpmc_onenand_resource = { @@ -38,11 +47,9 @@ static struct platform_device gpmc_onenand_device = { .resource = gpmc_onenand_resource, }; -static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) +static struct gpmc_timings omap2_onenand_calc_async_timings(void) { struct gpmc_timings t; - u32 reg; - int err; const int t_cer = 15; const int t_avdp = 12; @@ -55,11 +62,6 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) const int t_wpl = 40; const int t_wph = 30; - /* Ensure sync read and sync write are disabled */ - reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); - reg = ~ONENAND_SYS_CFG1_SYNC_READ ~ONENAND_SYS_CFG1_SYNC_WRITE; - writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); - memset(t, 0, sizeof(t)); t.sync_clk = 0; t.cs_on = 0; @@ -86,25 +88,30 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); + return t; +} + +static int gpmc_set_async_mode(int cs, struct gpmc_timings *t) +{ /* Configure GPMC for asynchronous read */ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, GPMC_CONFIG1_DEVICESIZE_16 | GPMC_CONFIG1_MUXADDDATA); - err = gpmc_cs_set_timings(cs, t); - if (err) - return err; + return gpmc_cs_set_timings(cs, t); +} + +static void omap2_onenand_set_async_mode(void __iomem *onenand_base) +{ + u32 reg; /* Ensure sync read and sync write are disabled */ reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); reg = ~ONENAND_SYS_CFG1_SYNC_READ ~ONENAND_SYS_CFG1_SYNC_WRITE; writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); - - return 0; } -static void set_onenand_cfg(void __iomem *onenand_base, int latency, - int sync_read, int sync_write, int hf, int vhf) +static void set_onenand_cfg(void __iomem *onenand_base) { u32 reg; @@ -112,19 +119,19 @@ static void set_onenand_cfg(void __iomem *onenand_base, int latency, reg = ~((0x7 ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 9)); reg |= (latency ONENAND_SYS_CFG1_BRL_SHIFT) | ONENAND_SYS_CFG1_BL_16; - if (sync_read) + if (onenand_flags ONENAND_FLAG_SYNCREAD) reg |= ONENAND_SYS_CFG1_SYNC_READ; else reg = ~ONENAND_SYS_CFG1_SYNC_READ; - if (sync_write) + if (onenand_flags ONENAND_FLAG_SYNCWRITE) reg |= ONENAND_SYS_CFG1_SYNC_WRITE; else reg = ~ONENAND_SYS_CFG1_SYNC_WRITE; - if (hf) + if (onenand_flags ONENAND_FLAG_HF) reg |= ONENAND_SYS_CFG1_HF; else reg = ~ONENAND_SYS_CFG1_HF; - if (vhf) + if (onenand_flags ONENAND_FLAG_VHF) reg |= ONENAND_SYS_CFG1_VHF; else reg = ~ONENAND_SYS_CFG1_VHF; @@ -172,9 +179,9 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, return freq; } -static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, -
[PATCH v6 04/10] ARM: OMAP2+: GPMC: Remove unused OneNAND get_freq() platform function
From: Jon Hunter jon-hun...@ti.com A platform function pointer for getting the frequency of a OneNAND device was added so that a platform could specify a custom function for returning the frequency and not just rely on the OneNAND version to determine the frequency. However, this platform function pointer is not currently being used and I am not sure if it ever has. OneNAND devices are not so common these days and as far as I know not being used with new devices. Therefore, it is most likely that this get_freq() function pointer will not be used and so remove it. Given that the get_freq() function pointer is not used, neither is the clk_dep variable and so all references to it can also be removed. Signed-off-by: Jon Hunter jon-hun...@ti.com Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-onenand.c| 39 +++- arch/arm/plat-omap/include/plat/onenand.h |8 -- 2 files changed, 5 insertions(+), 42 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index bbae674..8a301f3 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -139,21 +139,10 @@ static void set_onenand_cfg(void __iomem *onenand_base) } static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, - void __iomem *onenand_base, bool *clk_dep) + void __iomem *onenand_base) { u16 ver = readw(onenand_base + ONENAND_REG_VERSION_ID); - int freq = 0; - - if (cfg-get_freq) { - struct onenand_freq_info fi; - - fi.maf_id = readw(onenand_base + ONENAND_REG_MANUFACTURER_ID); - fi.dev_id = readw(onenand_base + ONENAND_REG_DEVICE_ID); - fi.ver_id = ver; - freq = cfg-get_freq(fi, clk_dep); - if (freq) - return freq; - } + int freq; switch ((ver 4) 0xf) { case 0: @@ -181,7 +170,7 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, static struct gpmc_timings omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, - int freq, bool clk_dep) + int freq) { struct gpmc_timings t; const int t_cer = 15; @@ -259,22 +248,6 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, else latency = 4; - if (clk_dep) { - if (gpmc_clk_ns 12) { /* 83Mhz */ - t_ces = 3; - t_avds = 4; - } else if (gpmc_clk_ns 15) { /* 66Mhz */ - t_ces = 5; - t_avds = 4; - } else if (gpmc_clk_ns 25) { /* 40Mhz */ - t_ces = 6; - t_avds = 5; - } else { - t_ces = 7; - t_avds = 7; - } - } - /* Set synchronous read timings */ memset(t, 0, sizeof(t)); @@ -381,16 +354,14 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr) { int ret, freq = *freq_ptr; struct gpmc_timings t; - bool clk_dep = false; if (!freq) { /* Very first call freq is not known */ - freq = omap2_onenand_get_freq(gpmc_onenand_data, - onenand_base, clk_dep); + freq = omap2_onenand_get_freq(gpmc_onenand_data, onenand_base); set_onenand_cfg(onenand_base); } - t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq, clk_dep); + t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq); ret = gpmc_set_sync_mode(gpmc_onenand_data-cs, t); if (IS_ERR_VALUE(ret)) diff --git a/arch/arm/plat-omap/include/plat/onenand.h b/arch/arm/plat-omap/include/plat/onenand.h index 2858667..21bb0ff 100644 --- a/arch/arm/plat-omap/include/plat/onenand.h +++ b/arch/arm/plat-omap/include/plat/onenand.h @@ -15,20 +15,12 @@ #define ONENAND_SYNC_READ (1 0) #define ONENAND_SYNC_READWRITE (1 1) -struct onenand_freq_info { - u16 maf_id; - u16 dev_id; - u16 ver_id; -}; - struct omap_onenand_platform_data { int cs; int gpio_irq; struct mtd_partition*parts; int nr_parts; int (*onenand_setup)(void __iomem *, int *freq_ptr); - int (*get_freq)(const struct onenand_freq_info *freq_info, - bool *clk_dep); int dma_channel; u8 flags; u8
[PATCH v6 05/10] ARM: OMAP2+: gpmc: find features by ip rev check
Newer IP's have wr_access and wr_data_mux_bus fields. Use IP revision values to determine availability of these fields and hence decide on whether to configure them. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 12 ++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 070fac5..68123d0 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -85,6 +85,11 @@ #define ENABLE_PREFETCH(0x1 7) #define DMA_MPU_MODE 2 +#defineGPMC_REVISION_MAJOR(l) ((l 4) 0xf) + +#defineGPMC_HAS_WR_ACCESS 0x1 +#defineGPMC_HAS_WR_DATA_MUX_BUS0x2 + /* XXX: Only NAND irq has been considered,currently these are the only ones used */ #defineGPMC_NR_IRQ 2 @@ -131,6 +136,7 @@ static DEFINE_SPINLOCK(gpmc_mem_lock); static unsigned int gpmc_cs_map; /* flag for cs which are initialized */ static int gpmc_ecc_used = -EINVAL;/* cs using ecc engine */ +static unsigned gpmc_capability; static void __iomem *gpmc_base; static struct clk *gpmc_l3_clk; @@ -356,10 +362,10 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring); GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation); - if (cpu_is_omap34xx()) { + if (gpmc_capability GPMC_HAS_WR_DATA_MUX_BUS) GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus); + if (gpmc_capability GPMC_HAS_WR_ACCESS) GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access); - } /* caller is expected to have initialized CONFIG1 to cover * at least sync vs async @@ -922,6 +928,8 @@ static int __init gpmc_init(void) clk_enable(gpmc_l3_clk); l = gpmc_read_reg(GPMC_REVISION); + if (GPMC_REVISION_MAJOR(l) 0x4) + gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS; printk(KERN_INFO GPMC revision %d.%d\n, (l 4) 0x0f, l 0x0f); /* Set smart idle mode and automatic L3 clock gating */ l = gpmc_read_reg(GPMC_SYSCONFIG); -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v6 06/10] ARM: OMAP2+: gpmc: remove cs# in sync clk div calc
Divider value for a certain sync clk is determined solely based on gpmc fclk. CS# does not have any role here, thus remove presence of CS# in clock divider calculation API. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-onenand.c |3 +-- arch/arm/mach-omap2/gpmc.c |4 ++-- arch/arm/plat-omap/include/plat/gpmc.h |2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 8a301f3..e139e3f 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -182,7 +182,6 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns; int ticks_cez; - int cs = cfg-cs; if (cfg-flags ONENAND_SYNC_READ) onenand_flags = ONENAND_FLAG_SYNCREAD; @@ -229,7 +228,7 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, break; } - div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period); + div = gpmc_calc_divider(min_gpmc_clk_period); gpmc_clk_ns = gpmc_ticks_to_ns(div); if (gpmc_clk_ns 15) /* 66Mhz */ onenand_flags |= ONENAND_FLAG_HF; diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 68123d0..d005b3a 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -313,7 +313,7 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, return -1 #endif -int gpmc_cs_calc_divider(int cs, unsigned int sync_clk) +int gpmc_calc_divider(unsigned int sync_clk) { int div; u32 l; @@ -333,7 +333,7 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) int div; u32 l; - div = gpmc_cs_calc_divider(cs, t-sync_clk); + div = gpmc_calc_divider(t-sync_clk); if (div 0) return -1; diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index b7c9ea6..1cafbfd 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -179,7 +179,7 @@ extern unsigned long gpmc_get_fclk_period(void); extern void gpmc_cs_write_reg(int cs, int idx, u32 val); extern u32 gpmc_cs_read_reg(int cs, int idx); -extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk); +extern int gpmc_calc_divider(unsigned int sync_clk); extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t); extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base); extern void gpmc_cs_free(int cs); -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/4] Add mfd driver for smsc-ece1099 chip
Add a smsc-ece1099 mfd driver which will work as keypad scan device or a gpio expander device. Patch 1 creates the parent mfd driver. Patch 2 add keypad support. Patch 3 adds dts support for keypad in omap5 dts file. Patch 4 add gpio expansion driver for chip (RFC). Cc: Benoit Cousson b-cous...@ti.com Cc: Felipe Balbi ba...@ti.com Cc: Santosh Shilimkar santosh.shilim...@ti.com G, Manjunath Kondaiah (1): Input: keypad: Add smsc ece1099 keypad driver Sourav Poddar (3): mfd: smsc: Add support for smsc gpio io/keypad driver arm/dts: omap5-evm: Add keypad support gpio: smscece: Add support for gpio IO expander feature Documentation/smsc_ece1099.txt | 56 arch/arm/boot/dts/omap5-evm.dts | 95 +++ drivers/gpio/Kconfig |7 + drivers/gpio/Makefile|1 + drivers/gpio/gpio-smscece.c | 373 ++ drivers/input/keyboard/Kconfig | 11 + drivers/input/keyboard/Makefile |1 + drivers/input/keyboard/smsc-ece1099-keypad.c | 308 + drivers/mfd/Kconfig | 10 + drivers/mfd/Makefile |1 + drivers/mfd/smsc-ece1099.c | 139 ++ include/linux/mfd/smsc.h | 89 ++ 12 files changed, 1091 insertions(+), 0 deletions(-) create mode 100644 Documentation/smsc_ece1099.txt create mode 100644 drivers/gpio/gpio-smscece.c create mode 100644 drivers/input/keyboard/smsc-ece1099-keypad.c create mode 100644 drivers/mfd/smsc-ece1099.c create mode 100644 include/linux/mfd/smsc.h -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/4] Input: keypad: Add smsc ece1099 keypad driver
From: G, Manjunath Kondaiah manj...@ti.com SMSC ECE1099 is a keyboard scan or GPIO expansion device.The device supports a keypad scan matrix of 23*8.This driver uses this device as a keypad driver. Cc: Dmitry Torokhov dmitry.torok...@gmail.com Cc: Benoit Cousson b-cous...@ti.com Cc: Felipe Balbi ba...@ti.com Cc: Santosh Shilimkar santosh.shilim...@ti.com Signed-off-by: G, Manjunath Kondaiah manj...@ti.com Signed-off-by: Sourav Poddar sourav.pod...@ti.com --- drivers/input/keyboard/Kconfig | 11 + drivers/input/keyboard/Makefile |1 + drivers/input/keyboard/smsc-ece1099-keypad.c | 308 ++ 3 files changed, 320 insertions(+), 0 deletions(-) create mode 100644 drivers/input/keyboard/smsc-ece1099-keypad.c diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index c50fa75..2a2d374 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -593,6 +593,17 @@ config KEYBOARD_TWL4030 To compile this driver as a module, choose M here: the module will be called twl4030_keypad. +config KEYBOARD_SMSC + tristate SMSC ECE1099 keypad support + depends on I2C=y + help + Say Y here if your board use the smsc keypad controller + for omap5 defconfig. It's safe to say enable this + even on boards that don't use the keypad controller. + + To compile this driver as a module, choose M here: the + module will be called smsc-ece1099-keypad. + config KEYBOARD_XTKBD tristate XT keyboard select SERIO diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 44e7600..0f2aa26 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -52,5 +52,6 @@ obj-$(CONFIG_KEYBOARD_TC3589X)+= tc3589x-keypad.o obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o +obj-$(CONFIG_KEYBOARD_SMSC)+= smsc-ece1099-keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o diff --git a/drivers/input/keyboard/smsc-ece1099-keypad.c b/drivers/input/keyboard/smsc-ece1099-keypad.c new file mode 100644 index 000..8a77878 --- /dev/null +++ b/drivers/input/keyboard/smsc-ece1099-keypad.c @@ -0,0 +1,308 @@ +/* + * SMSC_ECE1099 Keypad driver + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include linux/i2c.h +#include linux/kernel.h +#include linux/module.h +#include linux/init.h +#include linux/interrupt.h +#include linux/input.h +#include linux/gpio.h +#include linux/slab.h +#include linux/jiffies.h +#include linux/input/matrix_keypad.h +#include linux/delay.h +#include linux/mfd/core.h +#include linux/mfd/smsc.h +#include linux/of_gpio.h +#include linux/of.h + +#define KEYPRESS_TIME 200 + +struct smsc_keypad { + struct smsc *smsc; + struct matrix_keymap_data *keymap_data; + unsigned int last_key_state[16]; + unsigned int last_col; + unsigned int last_key_ms[16]; + unsigned short *keymap; + struct i2c_client *client; + struct input_dev *input; + int rows, cols; + int row_shift; + bool no_autorepeat; + unsignedirq; + struct device *dev; +}; + +static void smsc_kp_scan(struct smsc_keypad *kp) +{ + struct input_dev *input = kp-input; + int i, j; + int row, col; + int temp, code; + unsigned int new_state[16]; + unsigned int bits_changed; + int this_ms; + + smsc_write(kp-dev, SMSC_KP_INT_MASK, 0x00); + smsc_write(kp-dev, SMSC_KP_INT_STAT, 0xFF); + + /* Scan for row and column */ + for (i = 0; i kp-cols; i++) { + smsc_write(kp-dev, SMSC_KP_OUT, SMSC_KSO_EVAL + i); + /* Read Row Status */ + smsc_read(kp-dev, SMSC_KP_IN, temp); + if (temp == 0xFF) + continue; + + col = i; + for (j = 0; j kp-rows; j++) { + if ((temp 0x01) != 0x00) { + temp = temp 1; + continue; + } + + row = j; + new_state[col] = (1 row); + bits_changed = kp-last_key_state[col] ^ new_state[col]; + this_ms = jiffies_to_msecs(jiffies); + if (bits_changed != 0 || (!bits_changed + ((this_ms - kp-last_key_ms[col]) = KEYPRESS_TIME))) { + code = MATRIX_SCAN_CODE(row,
[PATCH v6 10/10] ARM: OMAP2+: tusb6010: generic timing calculation
Generic gpmc timing calculation helper is available now, use it instead of custom timing calculation. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/usb-tusb6010.c | 181 +--- 1 files changed, 43 insertions(+), 138 deletions(-) diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c index 7a85ebe..cce1f06 100644 --- a/arch/arm/mach-omap2/usb-tusb6010.c +++ b/arch/arm/mach-omap2/usb-tusb6010.c @@ -26,182 +26,87 @@ static u8 async_cs, sync_cs; static unsignedrefclk_psec; -/* t2_ps, when quantized to fclk units, must happen no earlier than - * the clock after after t1_NS. - * - * Return a possibly updated value of t2_ps, converted to nsec. - */ -static unsigned -next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps) -{ - unsignedt1_ps = t1_NS * 1000; - unsignedt1_f, t2_f; - - if ((t1_ps + fclk_ps) t2_ps) - return t2_ps / 1000; - - t1_f = (t1_ps + fclk_ps - 1) / fclk_ps; - t2_f = (t2_ps + fclk_ps - 1) / fclk_ps; - - if (t1_f = t2_f) - t2_f = t1_f + 1; - - return (t2_f * fclk_ps) / 1000; -} - /* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */ -static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps) +static int tusb_set_async_mode(unsigned sysclk_ps) { + struct gpmc_device_timings dev_t; struct gpmc_timings t; unsignedt_acsnh_advnh = sysclk_ps + 3000; - unsignedtmp; - - memset(t, 0, sizeof(t)); - - /* CS_ON = t_acsnh_acsnl */ - t.cs_on = 8; - /* ADV_ON = t_acsnh_advnh - t_advn */ - t.adv_on = next_clk(t.cs_on, t_acsnh_advnh - 7000, fclk_ps); - - /* -* READ ... from omap2420 TRM fig 12-13 -*/ - - /* ADV_RD_OFF = t_acsnh_advnh */ - t.adv_rd_off = next_clk(t.adv_on, t_acsnh_advnh, fclk_ps); - - /* OE_ON = t_acsnh_advnh + t_advn_oen (then wait for nRDY) */ - t.oe_on = next_clk(t.adv_on, t_acsnh_advnh + 1000, fclk_ps); - - /* ACCESS = counters continue only after nRDY */ - tmp = t.oe_on * 1000 + 300; - t.access = next_clk(t.oe_on, tmp, fclk_ps); - - /* OE_OFF = after data gets sampled */ - tmp = t.access * 1000; - t.oe_off = next_clk(t.access, tmp, fclk_ps); - - t.cs_rd_off = t.oe_off; - - tmp = t.cs_rd_off * 1000 + 7000 /* t_acsn_rdy_z */; - t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps); - - /* -* WRITE ... from omap2420 TRM fig 12-15 -*/ - /* ADV_WR_OFF = t_acsnh_advnh */ - t.adv_wr_off = t.adv_rd_off; + memset(dev_t, 0, sizeof(dev_t)); - /* WE_ON = t_acsnh_advnh + t_advn_wen (then wait for nRDY) */ - t.we_on = next_clk(t.adv_wr_off, t_acsnh_advnh + 1000, fclk_ps); + dev_t.mux = true; - /* WE_OFF = after data gets sampled */ - tmp = t.we_on * 1000 + 300; - t.we_off = next_clk(t.we_on, tmp, fclk_ps); + dev_t.t_ceasu = 8 * 1000; + dev_t.t_avdasu = t_acsnh_advnh - 7000; + dev_t.t_ce_avd = 1000; + dev_t.t_avdp_r = t_acsnh_advnh; + dev_t.t_oeasu = t_acsnh_advnh + 1000; + dev_t.t_oe = 300; + dev_t.t_cez_r = dev_t.t_cez_w = 7000; + dev_t.t_avdp_w = t_acsnh_advnh; + dev_t.t_weasu = t_acsnh_advnh + 1000; + dev_t.t_wpl = 300; + dev_t.cyc_aavdh_we = 1; - t.cs_wr_off = t.we_off; - - tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */; - t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps); + gpmc_calc_timings(t, dev_t); return gpmc_cs_set_timings(async_cs, t); } -static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps) +static int tusb_set_sync_mode(unsigned sysclk_ps) { + struct gpmc_device_timings dev_t; struct gpmc_timings t; unsignedt_scsnh_advnh = sysclk_ps + 3000; - unsignedtmp; - - memset(t, 0, sizeof(t)); - t.cs_on = 8; - - /* ADV_ON = t_acsnh_advnh - t_advn */ - t.adv_on = next_clk(t.cs_on, t_scsnh_advnh - 7000, fclk_ps); - - /* GPMC_CLK rate = fclk rate / div */ - t.sync_clk = 11100 /* 11.1 nsec */; - tmp = (t.sync_clk + fclk_ps - 1) / fclk_ps; - if (tmp 4) - return -ERANGE; - if (tmp == 0) - tmp = 1; - t.page_burst_access = (fclk_ps * tmp) / 1000; - - /* -* READ ... based on omap2420 TRM fig 12-19, 12-20 -*/ - - /* ADV_RD_OFF = t_scsnh_advnh */ - t.adv_rd_off = next_clk(t.adv_on, t_scsnh_advnh, fclk_ps); - - /* OE_ON = t_scsnh_advnh + t_advn_oen * fclk_ps (then wait for nRDY) */ - tmp = (t.adv_rd_off * 1000) + (3 * fclk_ps); - t.oe_on = next_clk(t.adv_on, tmp, fclk_ps); - - /* ACCESS = number of clock cycles after t_adv_eon */ - tmp = (t.oe_on * 1000) + (5 * fclk_ps); -
[PATCH 3/4] arm/dts: omap5-evm: Add keypad support
Add keypad data node in omap5-evm. Based on I2C support patch for omap5, which has been already posted as a different series. Cc: Benoit Cousson b-cous...@ti.com Cc: Felipe Balbi ba...@ti.com Cc: Santosh Shilimkar santosh.shilim...@ti.com Tested on omap5430 sdp with 3.5 custom kernel. Signed-off-by: Sourav Poddar sourav.pod...@ti.com --- arch/arm/boot/dts/omap5-evm.dts | 95 +++ 1 files changed, 95 insertions(+), 0 deletions(-) diff --git a/arch/arm/boot/dts/omap5-evm.dts b/arch/arm/boot/dts/omap5-evm.dts index 200c39a..6473983 100644 --- a/arch/arm/boot/dts/omap5-evm.dts +++ b/arch/arm/boot/dts/omap5-evm.dts @@ -18,3 +18,98 @@ reg = 0x8000 0x4000; /* 1 GB */ }; }; + +i2c5 { + clock-frequency = 40; + + smsc@38 { + compatible = smsc; + reg = 0x38; + clock = 0x13; + keypad { + compatible = smsc,keypad; + interrupt-parent = gpio5; + interrupts = 23; /* gpio line 151 */ + keypad,num-rows = 8; + keypad,num-columns = 16; + linux,keymap = 0x20041 /*KEY_F7*/ + 0x30001 /*KEY_ESC*/ + 0x4003e /*KEY_F4*/ + 0x50022 /*KEY_G*/ + 0x70023 /*KEY_H*/ + 0x9009a /*KEY_CYCLEWINDOWS*/ + 0xc000e /*KEY_BACKSPACE*/ + 0xd0057 /*KEY_F11*/ + 0xe009f /*KEY_FORWARD*/ + 0xf006e /*KEY_INSERT*/ + 0x1020036 /*KEY_RIGHTSHIFT*/ + 0x1030011 /*KEY_W*/ + 0x1040010 /*KEY_Q*/ + 0x1050012 /*KEY_E*/ + 0x1070013 /*KEY_R*/ + 0x1080016 /*KEY_U*/ + 0x10c0017 /*KEY_I*/ + 0x10d0067 /*KEY_UP*/ + 0x10e0018 /*KEY_O*/ + 0x10f0019 /*KEY_LEFT*/ + 0x2020003 /*KEY_2*/ + 0x2040004 /*KEY_1*/ + 0x2050005 /*KEY_3*/ + 0x2070008 /*KEY_4*/ + 0x2080009 /*KEY_7*/ + 0x20b0064 /*KEY_8*/ + 0x20c006c /*KEY_RIGHTALT*/ + 0x20d000a /*KEY_DOWN*/ + 0x20e0001 /*KEY_0*/ + 0x20f006a /*KEY_RIGHT*/ + 0x3010061 /*KEY_RIGHTCTRL*/ + 0x302001f /*KEY_S*/ + 0x303001e /*KEY_A*/ + 0x3040020 /*KEY_D*/ + 0x3050021 /*KEY_F*/ + 0x3070024 /*KEY_J*/ + 0x3080025 /*KEY_K*/ + 0x30c001c /*KEY_ENTER*/ + 0x30d0026 /*KEY_L*/ + 0x30e0027 /*KEY_SEMICOLON*/ + 0x42a /*KEY_LEFTSHIFT*/ + 0x402002d /*KEY_X*/ + 0x403002c /*KEY_Z*/ + 0x404002e /*KEY_C*/ + 0x405002f /*KEY_V/ + 0x4070032 /*KEY_M*/ + 0x4080033 /*KEY_COMMA*/ + 0x40c0039 /*KEY_SPACE*/ + 0x40d0033 /*KEY_DOT*/ + 0x40e0035 /*KEY_SLASH*/ + 0x40f006b /*KEY_END*/ + 0x501001d /*KEY_LEFTCTRL*/ + 0x5020040 /*KEY_F6*/ + 0x503000f /*KEY_TAB*/ + 0x504003d /*KEY_F3*/ + 0x5050014 /*KEY_T*/ + 0x5070015 /*KEY_Y*/ + 0x508001a /*KEY_LEFTBRACE*/ + 0x50d0044 /*KEY_F10*/ + 0x50e001b /*KEY_RIGHTBRACE*/ + 0x50f0066 /*KEY_HOME*/ +
[PATCH v6 09/10] ARM: OMAP2+: smc91x: generic timing calculation
Generic gpmc timing calculation helper is available now, use it instead of custom timing calculation. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-smc91x.c | 43 ++-- 1 files changed, 17 insertions(+), 26 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c index ba10c24..43900f9 100644 --- a/arch/arm/mach-omap2/gpmc-smc91x.c +++ b/arch/arm/mach-omap2/gpmc-smc91x.c @@ -57,6 +57,7 @@ static struct platform_device gpmc_smc91x_device = { static int smc91c96_gpmc_retime(void) { struct gpmc_timings t; + struct gpmc_device_timings dev_t; const int t3 = 10; /* Figure 12.2 read and 12.4 write */ const int t4_r = 20;/* Figure 12.2 read */ const int t4_w = 5; /* Figure 12.4 write */ @@ -67,32 +68,6 @@ static int smc91c96_gpmc_retime(void) const int t20 = 185;/* Figure 12.2 read and 12.4 write */ u32 l; - memset(t, 0, sizeof(t)); - - /* Read timings */ - t.cs_on = 0; - t.adv_on = t.cs_on; - t.oe_on = t.adv_on + t3; - t.access = t.oe_on + t5; - t.oe_off = t.access; - t.adv_rd_off = t.oe_off + max(t4_r, t6); - t.cs_rd_off = t.oe_off; - t.rd_cycle = t20 - t.oe_on; - - /* Write timings */ - t.we_on = t.adv_on + t3; - - if (cpu_is_omap34xx() (gpmc_cfg-flags GPMC_MUX_ADD_DATA)) { - t.wr_data_mux_bus = t.we_on; - t.we_off = t.wr_data_mux_bus + t7; - } else - t.we_off = t.we_on + t7; - if (cpu_is_omap34xx()) - t.wr_access = t.we_off; - t.adv_wr_off = t.we_off + max(t4_w, t8); - t.cs_wr_off = t.we_off + t4_w; - t.wr_cycle = t20 - t.we_on; - l = GPMC_CONFIG1_DEVICESIZE_16; if (gpmc_cfg-flags GPMC_MUX_ADD_DATA) l |= GPMC_CONFIG1_MUXADDDATA; @@ -114,6 +89,22 @@ static int smc91c96_gpmc_retime(void) if (gpmc_cfg-flags GPMC_MUX_ADD_DATA) return 0; + memset(dev_t, 0, sizeof(dev_t)); + + dev_t.t_oeasu = t3 * 1000; + dev_t.t_oe = t5 * 1000; + dev_t.t_cez_r = t4_r * 1000; + dev_t.t_oez = t6 * 1000; + dev_t.t_rd_cycle = (t20 - t3) * 1000; + + dev_t.t_weasu = t3 * 1000; + dev_t.t_wpl = t7 * 1000; + dev_t.t_wph = t8 * 1000; + dev_t.t_cez_w = t4_w * 1000; + dev_t.t_wr_cycle = (t20 - t3) * 1000; + + gpmc_calc_timings(t, dev_t); + return gpmc_cs_set_timings(gpmc_cfg-cs, t); } -- 1.7.1 -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/5] ARM: OMAP4: Add L2 Cache Controller in Device Tree
On Tue, Aug 21, 2012 at 4:14 PM, Benoit Cousson b-cous...@ti.com wrote: Hi Santosh, [...] From 91d6cb4f999061c8cfc844a3916ee3384f2e488a Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar santosh.shilim...@ti.com Date: Wed, 4 Jul 2012 17:57:34 +0530 Subject: [PATCH 1/2 v2] ARM: OMAP4: Add L2 Cache Controller in Device Tree This provides PL310 Level 2 Cache Controller Device Tree support for OMAP4 based devices. Cc: Benoit Cousson b-cous...@ti.com Signed-off-by: Santosh Shilimkar santosh.shilim...@ti.com nice work :-) FWIW this looks good to me: Acked-by: Felipe Balbi ba...@ti.com Thanks. just one thing, will a similar patch for omap3 be sent ? OMAP3 has an integrated L2 cache controller so there won't any additional DT node for L2. OMAP3 CPU DT node can be updated with l1/l2 cache size etc related information though. That's not needed if the information is available from the HW. DT is only there to provide information that cannot be extracted from HW. Good to know. If CP15 registers already contains the details about caches, then there is no need to add them in the DT file. True. In that case as you said, there is no need to add that information in DT. Regards Santosh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 09/10] mmc: omap_hsmmc: convert from IP timer to hrtimer
On Sat, Aug 18, 2012 at 12:22:29AM +0530, Venkatraman S wrote: omap hsmmc controller IP has an inbuilt timer that can be programmed to ^^^ built-in guard against unresponsive operations. But it's range is very narrow, its and it's maximum countable time is a few seconds. its Card maintenance operations like BKOPS and SECURE DISCARD and long stream writes like packed command require timers of order of several minutes. So get rid of using the IP timer entirely and use kernel's hrtimer functionality for guarding the device operations. As part of this change, a workaround that disabled timeouts for MMC_ERASE commands is removed, and the arbitary timing of 100ms is used only when the timeout is not explicitly specified by core. Signed-off-by: Venkatraman S svenk...@ti.com --- drivers/mmc/host/omap_hsmmc.c | 96 ++- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 9afdd20..8f7cebc 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -79,7 +79,7 @@ #define CLKD_SHIFT 6 #define DTO_MASK 0x000F #define DTO_SHIFT16 -#define INT_EN_MASK 0x307F0033 +#define INT_EN_MASK 0x306E0033 not related to this patch in particular, but it would be nice if this was converted to something more meaningfull, like ORing a bunch of bit defines. #define BWR_ENABLE (1 4) #define BRR_ENABLE (1 5) #define DTO_ENABLE (1 20) @@ -160,6 +160,7 @@ struct omap_hsmmc_host { unsigned intdma_sg_idx; unsigned char bus_mode; unsigned char power_mode; + unsigned intns_per_clk_cycle; int suspended; int irq; int use_dma, dma_ch; @@ -172,6 +173,7 @@ struct omap_hsmmc_host { int reqs_blocked; int use_reg; int req_in_progress; + struct hrtimer guard_timer; struct omap_hsmmc_next next_data; struct omap_mmc_platform_data *pdata; @@ -455,10 +457,6 @@ static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host, else irq_mask = INT_EN_MASK; - /* Disable timeout for erases */ - if (cmd-opcode == MMC_ERASE) - irq_mask = ~DTO_ENABLE; - OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); OMAP_HSMMC_WRITE(host-base, ISE, irq_mask); OMAP_HSMMC_WRITE(host-base, IE, irq_mask); @@ -508,6 +506,9 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host) time_before(jiffies, timeout)) cpu_relax(); + if (ios-clock) + host-ns_per_clk_cycle = DIV_ROUND_UP(NSEC_PER_SEC, ios-clock); + omap_hsmmc_start_clock(host); } @@ -824,7 +825,7 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) omap_hsmmc_request_done(host, mrq); return; } - + hrtimer_cancel(host-guard_timer); host-data = NULL; if (!data-error) @@ -859,8 +860,11 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) cmd-resp[0] = OMAP_HSMMC_READ(host-base, RSP10); } } - if ((host-data == NULL !host-response_busy) || cmd-error) + if ((host-data == NULL !host-response_busy) || cmd-error) { could just go ahead and make this check uniform by: if ((!host-data !host-response_busy)) || cmd-error) + if (cmd-error != -ETIMEDOUT) + hrtimer_cancel(host-guard_timer); omap_hsmmc_request_done(host, cmd-mrq); + } } /* @@ -992,7 +996,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) hsmmc_command_incomplete(host, -EILSEQ); end_cmd = 1; - if (host-data || host-response_busy) { + if (data || host-response_busy) { This doesn't seem like it belongs to $SUBJECT... end_trans = 1; host-response_busy = 0; } @@ -1292,41 +1296,35 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, return 0; } -static void set_data_timeout(struct omap_hsmmc_host *host, - unsigned int timeout_ns, - unsigned int timeout_clks) +static void set_guard_timer(struct omap_hsmmc_host *host, + unsigned long timeout_ms, unsigned long timeout_ns, + unsigned int timeout_clks) { - unsigned int timeout,
[RFC/PATCH 4/4] gpio: smscece: Add support for gpio IO expander feature
smsc can be used as an gpio io expander device also. So adding support for configuring smsc pins as a gpio. Cc: Benoit Cousson b-cous...@ti.com Cc: Felipe Balbi ba...@ti.com Cc: Santosh Shilimkar santosh.shilim...@ti.com Signed-off-by: Sourav Poddar sourav.pod...@ti.com --- drivers/gpio/Kconfig|7 + drivers/gpio/Makefile |1 + drivers/gpio/gpio-smscece.c | 373 +++ 3 files changed, 381 insertions(+), 0 deletions(-) create mode 100644 drivers/gpio/gpio-smscece.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b16c8a7..e883929 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -444,6 +444,13 @@ config GPIO_ADP5588_IRQ Say yes here to enable the adp5588 to be used as an interrupt controller. It requires the driver to be built in the kernel. +config GPIO_SMSCECE + tristate SMSCECE 1099 I2C GPIO expander + depends on I2C + help + This option enables support for 18 GPIOs found + on SMSC ECE 1099 GPIO Expanders. + comment PCI GPIO expanders: config GPIO_CS5535 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 153cace..7c803c5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o obj-$(CONFIG_GPIO_AB8500) += gpio-ab8500.o obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o +obj-$(CONFIG_GPIO_SMSCECE) += gpio-smscece.o obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o diff --git a/drivers/gpio/gpio-smscece.c b/drivers/gpio/gpio-smscece.c new file mode 100644 index 000..0cb0959 --- /dev/null +++ b/drivers/gpio/gpio-smscece.c @@ -0,0 +1,373 @@ +/* + * GPIO Chip driver for smsc + * SMSC I/O Expander and QWERTY Keypad Controller + * + * Copyright 2012 Texas Instruments Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include linux/module.h +#include linux/kernel.h +#include linux/slab.h +#include linux/init.h +#include linux/i2c.h +#include linux/gpio.h +#include linux/interrupt.h +#include linux/irqdomain.h +#include linux/irq.h +#include linux/mfd/smsc.h +#include linux/err.h + +struct smsc_gpio { + struct device *dev; + struct smsc *smsc; + struct gpio_chip gpio_chip; + struct mutex lock; /* protect cached dir, dat_out */ + /* protect serialized access to the interrupt controller bus */ + struct mutex irq_lock; + unsigned gpio_start; + int type; + int flags; + int irq; + int irq_base; + unsigned int gpio_base; + unsigned int dat_out[5]; + unsigned int dir[5]; + unsigned int int_lvl[5]; + unsigned int int_en[5]; + unsigned int irq_mask[5]; + unsigned int irq_stat[5]; +}; + +static int smsc_gpio_get_value(struct gpio_chip *chip, unsigned off) +{ + struct smsc_gpio *sg = + container_of(chip, struct smsc_gpio, gpio_chip); + unsigned int get; + return !!(smsc_read(sg-dev, + (SMSC_GPIO_DATA_IN_START + SMSC_BANK(off)) SMSC_BIT(off), + get)); +} + +static void smsc_gpio_set_value(struct gpio_chip *chip, + unsigned off, int val) +{ + unsigned bank, bit; + struct smsc_gpio *sg = + container_of(chip, struct smsc_gpio, gpio_chip); + + bank = SMSC_BANK(off); + bit = SMSC_BIT(off); + + mutex_lock(sg-lock); + if (val) + sg-dat_out[bank] |= bit; + else + sg-dat_out[bank] = ~bit; + + smsc_write(sg-dev, SMSC_GPIO_DATA_OUT_START + bank, + sg-dat_out[bank]); + mutex_unlock(sg-lock); +} + +static int smsc_gpio_direction_input(struct gpio_chip *chip, unsigned off) +{ + unsigned int reg; + struct smsc_gpio *sg = + container_of(chip, struct smsc_gpio, gpio_chip); + int reg_dir; + + mutex_lock(sg-lock); + reg_dir = SMSC_CFG_START + off; + smsc_read(sg-dev, reg_dir, reg); + reg |= SMSC_GPIO_INPUT_LOW; + mutex_unlock(sg-lock); + + return smsc_write(sg-dev, reg_dir, reg); +} + +static int smsc_gpio_direction_output(struct gpio_chip *chip, +unsigned off, int val) +{ + unsigned int reg; + struct smsc_gpio *sg = + container_of(chip, struct smsc_gpio, gpio_chip); + int reg_dir; + + mutex_lock(sg-lock); + reg_dir = SMSC_CFG_START + off; + smsc_read(sg-dev, reg_dir, reg); + reg |= SMSC_GPIO_OUTPUT_PP; + mutex_unlock(sg-lock); + + return smsc_write(sg-dev, reg_dir, reg); +} + +static int smsc_gpio_to_irq(struct gpio_chip *chip, unsigned off) +{ + struct smsc_gpio *sg = + container_of(chip, struct smsc_gpio, gpio_chip); +
[PATCH 1/4] mfd: smsc: Add support for smsc gpio io/keypad driver
smsc ece1099 is a keyboard scan or gpio expansion device. The patch create keypad and gpio expander child for this multi function smsc driver. Cc: Samuel Ortiz sa...@linux.intel.com Cc: Benoit Cousson b-cous...@ti.com Cc: Felipe Balbi ba...@ti.com Cc: Santosh Shilimkar santosh.shilim...@ti.com Signed-off-by: Sourav Poddar sourav.pod...@ti.com --- Documentation/smsc_ece1099.txt | 56 drivers/mfd/Kconfig| 10 +++ drivers/mfd/Makefile |1 + drivers/mfd/smsc-ece1099.c | 139 include/linux/mfd/smsc.h | 89 + 5 files changed, 295 insertions(+), 0 deletions(-) create mode 100644 Documentation/smsc_ece1099.txt create mode 100644 drivers/mfd/smsc-ece1099.c create mode 100644 include/linux/mfd/smsc.h diff --git a/Documentation/smsc_ece1099.txt b/Documentation/smsc_ece1099.txt new file mode 100644 index 000..6b492e8 --- /dev/null +++ b/Documentation/smsc_ece1099.txt @@ -0,0 +1,56 @@ +What is smsc-ece1099? +-- + +The ECE1099 is a 40-Pin 3.3V Keyboard Scan Expansion +or GPIO Expansion device. The device supports a keyboard +scan matrix of 23x8. The device is connected to a Master +via the SMSC BC-Link interface or via the SMBus. +Keypad scan Input(KSI) and Keypad Scan Output(KSO) signals +are multiplexed with GPIOs. + +Interrupt generation + + +Interrupts can be generated by an edge detection on a GPIO +pin or an edge detection on one of the bus interface pins. +Interrupts can also be detected on the keyboard scan interface. +The bus interrupt pin (BC_INT# or SMBUS_INT#) is asserted if +any bit in one of the Interrupt Status registers is 1 and +the corresponding Interrupt Mask bit is also 1. + +In order for software to determine which device is the source +of an interrupt, it should first read the Group Interrupt Status Register +to determine which Status register group is a source for the interrupt. +Software should read both the Status register and the associated Mask register, +then AND the two values together. Bits that are 1 in the result of the AND +are active interrupts. Software clears an interrupt by writing a 1 to the +corresponding bit in the Status register. + +Communication Protocol +-- + +- SMbus slave Interface + The host processor communicates with the ECE1099 device + through a series of read/write registers via the SMBus + interface. SMBus is a serial communication protocol between + a computer host and its peripheral devices. The SMBus data + rate is 10KHz minimum to 400 KHz maximum + +- Slave Bus Interface + The ECE1099 device SMBus implementation is a subset of the + SMBus interface to the host. The device is a slave-only SMBus device. + The implementation in the device is a subset of SMBus since it + only supports four protocols. + + The Write Byte, Read Byte, Send Byte, and Receive Byte protocols are the + only valid SMBus protocols for the device. + +- BC-LinkTM Interface + The BC-Link is a proprietary bus that allows communication + between a Master device and a Companion device. The Master + device uses this serial bus to read and write registers + located on the Companion device. The bus comprises three signals, + BC_CLK, BC_DAT and BC_INT#. The Master device always provides the + clock, BC_CLK, and the Companion device is the source for an + independent asynchronous interrupt signal, BC_INT#. The ECE1099 + supports BC-Link speeds up to 24MHz. diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index d1facef..3b81c17 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -385,6 +385,16 @@ config MFD_T7L66XB help Support for Toshiba Mobile IO Controller T7L66XB +config MFD_SMSC + bool Support for the SMSC ECE1099 series chips + depends on I2C=y MFD_CORE REGMAP_I2C + help +If you say yes here you get support for the +ece1099 chips from SMSC. + +To compile this driver as a module, choose M here: the +module will be called smsc. + config MFD_TC6387XB bool Support Toshiba TC6387XB depends on ARM HAVE_CLK diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 79dd22d..f587d91 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_EZX_PCAP)+= ezx-pcap.o obj-$(CONFIG_MCP) += mcp-core.o obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o +obj-$(CONFIG_MFD_SMSC)+= smsc.o obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o ifeq ($(CONFIG_SA1100_ASSABET),y) diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c new file mode 100644 index 000..6ba06b8 --- /dev/null +++ b/drivers/mfd/smsc-ece1099.c @@ -0,0 +1,139 @@ +/* + * TI SMSC MFD Driver + * + * Copyright
[PATCH v6 07/10] ARM: OMAP2+: gpmc: generic timing calculation
Presently there are three peripherals that gets it timing by runtime calculation. Those peripherals can work with frequency scaling that affects gpmc clock. But timing calculation for them are in different ways. Here a generic runtime calculation method is proposed. Input to this function were selected so that they represent timing variables that are present in peripheral datasheets. Motive behind this was to achieve DT bindings for the inputs as is. Even though a few of the tusb6010 timings could not be made directly related to timings normally found on peripherals, expressions used were translated to those that could be justified. There are possibilities of improving the calculations, like calculating timing for read write operations in a more similar way. Expressions derived here were tested for async onenand on omap3evm (as vanilla Kernel does not have omap3evm onenand support, local patch was used). Other peripherals, tusb6010, smc91x calculations were validated by simulating on omap3evm. Regarding we_on for onenand async, it was found that even for muxed address/data, it need not be greater than adv_wr_off, but rather could be derived from write setup time for peripheral from start of access time, hence would more be in line with peripheral timings. With this method it was working fine. If it is required in some cases to have we_on same as wr_data_mux_bus (i.e. greater than adv_wr_off), another variable could be added to indicate it. But such a requirement is not expected though. Whole of this exercise is being done to achieve driver and DT conversion. If timings could not be calculated in a peripheral agnostic way, either gpmc driver would have to be peripheral gnostic or a wrapper arrangement over gpmc driver would be required. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc.c | 302 arch/arm/plat-omap/include/plat/gpmc.h | 61 +++ 2 files changed, 363 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index d005b3a..d8e5b08 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -233,6 +233,18 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns) return ticks * gpmc_get_fclk_period() / 1000; } +unsigned int gpmc_ticks_to_ps(unsigned int ticks) +{ + return ticks * gpmc_get_fclk_period(); +} + +unsigned int gpmc_round_ps_to_ticks(unsigned int time_ps) +{ + unsigned long ticks = gpmc_ps_to_ticks(time_ps); + + return ticks * gpmc_get_fclk_period(); +} + static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value) { u32 l; @@ -884,6 +896,296 @@ static void __init gpmc_mem_init(void) } } +static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk) +{ + u32 temp; + int div; + + div = gpmc_calc_divider(sync_clk); + temp = gpmc_ps_to_ticks(time_ps); + temp = (temp + div - 1) / div; + return gpmc_ticks_to_ps(temp * div); +} + +/* can the cycles be avoided ? */ +static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t, + struct gpmc_device_timings *dev_t) +{ + bool mux = dev_t-mux; + u32 temp; + + /* adv_rd_off */ + temp = dev_t-t_avdp_r; + /* mux check required ? */ + if (mux) { + /* t_avdp not to be required for sync, only added for tusb this +* indirectly necessitates requirement of t_avdp_r t_avdp_w +* instead of having a single t_avdp +*/ + temp = max_t(u32, temp, gpmc_t-clk_activation * 1000 + + dev_t-t_avdh); + temp = max_t(u32, + (gpmc_t-adv_on + gpmc_ticks_to_ns(1)) * 1000, temp); + } + gpmc_t-adv_rd_off = gpmc_round_ps_to_ticks(temp) / 1000; + + /* oe_on */ + temp = dev_t-t_oeasu; /* remove this ? */ + if (mux) { + temp = max_t(u32, temp, + gpmc_t-clk_activation * 1000 + dev_t-t_ach); + temp = max_t(u32, temp, (gpmc_t-adv_rd_off + + gpmc_ticks_to_ns(dev_t-cyc_aavdh_oe)) * 1000); + } + gpmc_t-oe_on = gpmc_round_ps_to_ticks(temp) / 1000; + + /* access */ + /* any scope for improvement ?, by combining oe_on clk_activation, +* need to check whether access = clk_activation + round to sync clk ? +*/ + temp = max_t(u32, dev_t-t_iaa, dev_t-cyc_iaa * gpmc_t-sync_clk); + temp += gpmc_t-clk_activation * 1000; + if (dev_t-cyc_oe) + temp = max_t(u32, temp, (gpmc_t-oe_on + + gpmc_ticks_to_ns(dev_t-cyc_oe)) * 1000); + gpmc_t-access = gpmc_round_ps_to_ticks(temp) / 1000; + + gpmc_t-oe_off = gpmc_t-access + gpmc_ticks_to_ns(1); + gpmc_t-cs_rd_off = gpmc_t-oe_off; + + /* rd_cycle */ +
[PATCH v6 08/10] ARM: OMAP2+: onenand: generic timing calculation
Generic gpmc timing calculation helper is available now, use it instead of custom timing calculation. Signed-off-by: Afzal Mohammed af...@ti.com --- arch/arm/mach-omap2/gpmc-onenand.c | 124 1 files changed, 41 insertions(+), 83 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index e139e3f..700f9a6 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -49,6 +49,7 @@ static struct platform_device gpmc_onenand_device = { static struct gpmc_timings omap2_onenand_calc_async_timings(void) { + struct gpmc_device_timings dev_t; struct gpmc_timings t; const int t_cer = 15; @@ -58,35 +59,22 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void) const int t_aa = 76; const int t_oe = 20; const int t_cez = 20; /* max of t_cez, t_oez */ - const int t_ds = 30; const int t_wpl = 40; const int t_wph = 30; - memset(t, 0, sizeof(t)); - t.sync_clk = 0; - t.cs_on = 0; - t.adv_on = 0; - - /* Read */ - t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer)); - t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh); - t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa); - t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce)); - t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe)); - t.oe_off = t.access + gpmc_round_ns_to_ticks(1); - t.cs_rd_off = t.oe_off; - t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez); - - /* Write */ - t.adv_wr_off = t.adv_rd_off; - t.we_on = t.oe_on; - if (cpu_is_omap34xx()) { - t.wr_data_mux_bus = t.we_on; - t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds); - } - t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl); - t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); - t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); + memset(dev_t, 0, sizeof(dev_t)); + + dev_t.mux = true; + dev_t.t_avdp_r = dev_t.t_avdp_w = max_t(int, t_avdp, t_cer) * 1000; + dev_t.t_aavdh = t_aavdh * 1000; + dev_t.t_aa = t_aa * 1000; + dev_t.t_ce = t_ce * 1000; + dev_t.t_oe = t_oe * 1000; + dev_t.t_cez_r = dev_t.t_cez_w = t_cez * 1000; + dev_t.t_wpl = t_wpl * 1000; + dev_t.t_wph = t_wph * 1000; + + gpmc_calc_timings(t, dev_t); return t; } @@ -172,16 +160,15 @@ static struct gpmc_timings omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, int freq) { + struct gpmc_device_timings dev_t; struct gpmc_timings t; const int t_cer = 15; const int t_avdp = 12; const int t_cez = 20; /* max of t_cez, t_oez */ - const int t_ds = 30; const int t_wpl = 40; const int t_wph = 30; int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; - int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns; - int ticks_cez; + int div, gpmc_clk_ns; if (cfg-flags ONENAND_SYNC_READ) onenand_flags = ONENAND_FLAG_SYNCREAD; @@ -248,62 +235,33 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg, latency = 4; /* Set synchronous read timings */ - memset(t, 0, sizeof(t)); + memset(dev_t, 0, sizeof(dev_t)); - if (div == 1) { - t.bool_timings.cs_extra_delay = true; - t.bool_timings.adv_extra_delay = true; - t.bool_timings.oe_extra_delay = true; - t.bool_timings.we_extra_delay = true; - } - - t.sync_clk = min_gpmc_clk_period; - t.cs_on = 0; - t.adv_on = 0; - fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds)); - fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns); - t.page_burst_access = gpmc_clk_ns; - - /* Read */ - t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh)); - t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach)); - /* Force at least 1 clk between AVD High to OE Low */ - if (t.oe_on = t.adv_rd_off) - t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1); - t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div); - t.oe_off = t.access + gpmc_round_ns_to_ticks(1); - t.cs_rd_off = t.oe_off; - ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div; - t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div + -ticks_cez); - - t.clk_activation = fclk_offset_ns; - - /* Write */ - if (onenand_flags ONENAND_FLAG_SYNCWRITE) { - t.adv_wr_off = t.adv_rd_off; - t.we_on = 0; - t.we_off =
Re: [PATCH 00/10] Assorted MMC / OMAP HSMMC patches
Hi, On Sat, Aug 18, 2012 at 12:22:20AM +0530, Venkatraman S wrote: Essentially, a lot of cleanups leading up to adding a new feature for OMAP HSMMC. The idea is to convert to the use of software timer instead of IP timer for timekeeping, due to the limitations of the counting range of the IP timer. Also added myself as OMAP HSMMC maintainer. Patch 9/10 is in draft state and needs more testing. These patches are also available at git://github.com/svenkatr/linux.git my/mmc/3.6/hrtimer_updates other than the small comments I had to patch 9, this series looks very good: Acked-by: Felipe Balbi ba...@ti.com Venkatraman S (10): mmc: core: Add TRANsfer state to non-HPI state mmc: debugfs: Print ext_csd in ascending order mmc: omap: remove unused variables and includes mmc: omap: fix mmc_omap_report_irq to use dev_dbg macros mmc: omap_hsmmc: remove unused vars and includes mmc: omap_hsmmc: remove access to SYSCONFIG register mmc: omap_hsmmc: consolidate flush posted writes for HSMMC IRQs mmc: omap_hsmmc: consolidate error report handling of HSMMC IRQ mmc: omap_hsmmc: convert from IP timer to hrtimer mmc: omap_hsmmc: Move to Maintained state in MAINTAINERS MAINTAINERS | 4 +- drivers/mmc/core/core.c | 3 +- drivers/mmc/core/debugfs.c| 2 +- drivers/mmc/host/omap.c | 39 drivers/mmc/host/omap_hsmmc.c | 212 -- 5 files changed, 103 insertions(+), 157 deletions(-) -- 1.7.11.1.25.g0e18bef -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- balbi signature.asc Description: Digital signature
Re: [PATCH] OMAPDSS: Add timings for ChiMei G121S1-L01/L02 and G121X1-L01 LCD displays
On Wed, 2012-08-15 at 11:26 -0400, Raphaël Assénat wrote: + + /* ChiMei G121S1-L01 */ + { + { ... + .vsync_level= OMAPDSS_SIG_ACTIVE_HIGH, + .hsync_level= OMAPDSS_SIG_ACTIVE_HIGH, + .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, + .de_level = OMAPDSS_SIG_ACTIVE_HIGH, + .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, Actually those 3 panels only use the DE signal. The hsync/vsync signals are not used and on our system we mux them out to make sure they are kept low as recommended in the panel datasheets. Since vsync/hsync are not used, I think the vsync_level, hsync_level and sync_pclk_edge entries could be removed. Otherwise the updated patch works fine as is. Okay. How do panels like that work? How can they know where a new frame starts? Actually, I now googled for those panels, and they are all LVDS panels, not DPI panels. So the patch doesn't look correct at all. Do you have a DPI-to-LVDS converter chip on your board? Tomi signature.asc Description: This is a digitally signed message part
Re: [PATCH 2/4] Input: keypad: Add smsc ece1099 keypad driver
On Tue, Aug 21, 2012 at 04:15:38PM +0530, Sourav Poddar wrote: From: G, Manjunath Kondaiah manj...@ti.com SMSC ECE1099 is a keyboard scan or GPIO expansion device.The device supports a keypad scan matrix of 23*8.This driver uses this device as a keypad driver. Cc: Dmitry Torokhov dmitry.torok...@gmail.com Cc: Benoit Cousson b-cous...@ti.com Cc: Felipe Balbi ba...@ti.com Cc: Santosh Shilimkar santosh.shilim...@ti.com Signed-off-by: G, Manjunath Kondaiah manj...@ti.com Signed-off-by: Sourav Poddar sourav.pod...@ti.com looks good. If you just fix my comment on free_irq() below, you can add: Acked-by: Felipe Balbi ba...@ti.com +static int __devinit +smsc_probe(struct platform_device *pdev) +{ + struct device *dev = pdev-dev; + struct smsc *smsc = dev_get_drvdata(pdev-dev.parent); + struct input_dev *input; + struct smsc_keypad *kp; + int ret = 0, error; + int col, i, max_keys, row_shift; + int irq; + int addr_start, addr; + + kp = devm_kzalloc(dev, sizeof(*kp), GFP_KERNEL); + + input = input_allocate_device(); + if (!kp || !input) { + error = -ENOMEM; + goto err1; + } + + error = smsc_keypad_parse_dt(pdev-dev, kp); + if (error) + return error; + + /* Get the debug Device */ + kp-input = input; + kp-smsc = smsc; + kp-irq = platform_get_irq(pdev, 0); + kp-dev = dev; + + for (col = 0; col 16; col++) { + kp-last_key_state[col] = 0; + kp-last_key_ms[col] = 0; + } + + /* setup input device */ + __set_bit(EV_KEY, input-evbit); + + /* Enable auto repeat feature of Linux input subsystem */ + if (!(kp-no_autorepeat)) + __set_bit(EV_REP, input-evbit); + + input_set_capability(input, EV_MSC, MSC_SCAN); + input-name = SMSC Keypad; + input-phys = smsc_keypad/input0; + input-dev.parent = pdev-dev; + input-id.bustype = BUS_HOST; + input-id.vendor= 0x0001; + input-id.product = 0x0001; + input-id.version = 0x0003; + + error = input_register_device(input); + if (error) { + dev_err(kp-dev, + Unable to register twl4030 keypad device\n); + goto err1; + } + + /* Mask all GPIO interrupts (0x37-0x3B) */ + for (addr = 0x37; addr 0x3B; addr++) + smsc_write(dev, addr, 0); + + /* Set all outputs high (0x05-0x09) */ + for (addr = 0x05; addr 0x09; addr++) + smsc_write(dev, addr, 0xff); + + /* Clear all GPIO interrupts (0x32-0x36) */ + for (addr = 0x32; addr 0x36; addr++) + smsc_write(dev, addr, 0xff); + + addr_start = 0x12; + for (i = 0; i = kp-rows; i++) { + addr = 0x12 + i; + smsc_write(dev, addr, SMSC_KP_KSI); + } + + addr_start = 0x1A; + for (i = 0; i = kp-cols; i++) { + addr = 0x1A + i; + smsc_write(dev, addr, SMSC_KP_KSO); + } + + addr = SMSC_KP_INT_STAT; + smsc_write(dev, addr, SMSC_KP_SET_HIGH); + + addr = SMSC_WKUP_CTRL; + smsc_write(dev, addr, SMSC_KP_SET_LOW_PWR); + + addr = SMSC_KP_OUT; + smsc_write(dev, addr, SMSC_KSO_ALL_LOW); + + row_shift = get_count_order(kp-cols); + max_keys = kp-rows row_shift; + + kp-row_shift = row_shift; + kp-keymap = kzalloc(max_keys * sizeof(kp-keymap[0]), + GFP_KERNEL); + if (!kp-keymap) { + dev_err(pdev-dev, Not enough memory for keymap\n); + error = -ENOMEM; + } + + matrix_keypad_build_keymap(NULL, NULL, kp-rows, + kp-cols, kp-keymap, input); + + /* + * This ISR will always execute in kernel thread context because of + * the need to access the SMSC over the I2C bus. + */ + ret = devm_request_threaded_irq(dev, kp-irq, NULL, do_kp_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, pdev-name, kp); + if (ret) { + dev_dbg(pdev-dev, request_irq failed for irq no=%d\n, + irq); + goto err2; + } + + /* Enable smsc keypad interrupts */ + ret = smsc_write(dev, SMSC_KP_INT_MASK, 0xff); + if (ret 0) + goto err2; + + return 0; + +err2: + input_unregister_device(input); + free_irq(kp-irq, NULL); you're using devm_request_threaded_irq, this is unnecessary +err1: + input_free_device(input); + return ret; +} + +static int smsc_remove(struct platform_device *pdev) +{ + struct smsc_keypad *kp = platform_get_drvdata(pdev); + free_irq(kp-irq, kp); ditto. -- balbi signature.asc Description: Digital signature
Re: [PATCH 2/4] Input: keypad: Add smsc ece1099 keypad driver
Hi, On Tue, Aug 21, 2012 at 04:15:38PM +0530, Sourav Poddar wrote: +static struct platform_driver smsc_driver = { + .driver = { + .name = smsc-keypad, + .of_match_table = of_match_ptr(smsc_keypad_dt_match), + .owner = THIS_MODULE, + }, + .probe = smsc_probe, + .remove = smsc_remove, one extra comment which I forgot. You probably should put your remove on __devexit and add __devexit_p(smsc_remove) here. -- balbi signature.asc Description: Digital signature
Re: [PATCH 3/4] arm/dts: omap5-evm: Add keypad support
On Tue, Aug 21, 2012 at 04:15:39PM +0530, Sourav Poddar wrote: Add keypad data node in omap5-evm. Based on I2C support patch for omap5, which has been already posted as a different series. Cc: Benoit Cousson b-cous...@ti.com Cc: Felipe Balbi ba...@ti.com Cc: Santosh Shilimkar santosh.shilim...@ti.com Tested on omap5430 sdp with 3.5 custom kernel. Signed-off-by: Sourav Poddar sourav.pod...@ti.com after fixing my only comment below, you can add my: Acked-by: Felipe Balbi ba...@ti.com --- arch/arm/boot/dts/omap5-evm.dts | 95 +++ 1 files changed, 95 insertions(+), 0 deletions(-) diff --git a/arch/arm/boot/dts/omap5-evm.dts b/arch/arm/boot/dts/omap5-evm.dts index 200c39a..6473983 100644 --- a/arch/arm/boot/dts/omap5-evm.dts +++ b/arch/arm/boot/dts/omap5-evm.dts @@ -18,3 +18,98 @@ reg = 0x8000 0x4000; /* 1 GB */ }; }; + +i2c5 { + clock-frequency = 40; + + smsc@38 { + compatible = smsc; + reg = 0x38; + clock = 0x13; + keypad { + compatible = smsc,keypad; + interrupt-parent = gpio5; + interrupts = 23; /* gpio line 151 */ + keypad,num-rows = 8; + keypad,num-columns = 16; + linux,keymap = 0x20041 /*KEY_F7*/ please add spaces around /* and */ so it's easier to read. Ditto to all others. -- balbi signature.asc Description: Digital signature
RE: [PATCH v2 3/4] arm/dts: Add tps65910 regulator DT data to am335x-evm.dts
Hi Mark, On Tue, Aug 21, 2012 at 01:37:15, Mark Brown wrote: On Mon, Aug 20, 2012 at 06:27:01AM +, AnilKumar, Chimata wrote: On Thu, Aug 16, 2012 at 19:30:56, Mark Brown wrote: Why does this mean you need multiple regulators? A single regulator can of course supply multiple devices. I got your point but tps65910 driver is failing if we add single fixed regulator. Solution is driver needs to change or add multiple fixed regulators. No, really. One regulator can supply many things, not being a. vrtc: tps65910 0-002d: Failed to find supply vcc7 tps65910 0-002d: failed to register tps65910-pmic regulator So you've specified a whole bunch of supplies and this one individual supply is not matching (and it's not the first...). You should investigate what's gone wrong there rather than bodging around the problem. I can't immediately say anything much based on the information you've given. Sorry for the noise in this issue, I found the root cause. I was defining the supply names like this which is wrong. tps { regulators { vcc1-supply = vcc5v_supply; vcc2-supply = vcc5v_supply; vcc3-supply = vcc5v_supply; vcc4-supply = vcc5v_supply; vcc5-supply = vcc5v_supply; vcc6-supply = vcc5v_supply; vcc7-supply = vcc5v_supply; vccio-supply = vcc5v_supply; vrtc_reg: regulator@0 { /* vrtc input is vcc7 */ regulator-always-on; }; ... ... }; }; This was suppose to be tps { vcc1-supply = vcc5v_supply; vcc2-supply = vcc5v_supply; vcc3-supply = vcc5v_supply; vcc4-supply = vcc5v_supply; vcc5-supply = vcc5v_supply; vcc6-supply = vcc5v_supply; vcc7-supply = vcc5v_supply; vccio-supply = vcc5v_supply; regulators { vrtc_reg: regulator@0 { /* vrtc input is vcc7 */ regulator-always-on; }; ... ... }; }; Thanks for your continuous feedback. Thanks AnilKumar -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC/PATCH 4/4] gpio: smscece: Add support for gpio IO expander feature
Hi, On Tue, Aug 21, 2012 at 04:15:40PM +0530, Sourav Poddar wrote: smsc can be used as an gpio io expander device also. So adding support for configuring smsc pins as a gpio. Cc: Benoit Cousson b-cous...@ti.com Cc: Felipe Balbi ba...@ti.com Cc: Santosh Shilimkar santosh.shilim...@ti.com Signed-off-by: Sourav Poddar sourav.pod...@ti.com --- drivers/gpio/Kconfig|7 + drivers/gpio/Makefile |1 + drivers/gpio/gpio-smscece.c | 373 +++ 3 files changed, 381 insertions(+), 0 deletions(-) create mode 100644 drivers/gpio/gpio-smscece.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b16c8a7..e883929 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -444,6 +444,13 @@ config GPIO_ADP5588_IRQ Say yes here to enable the adp5588 to be used as an interrupt controller. It requires the driver to be built in the kernel. +config GPIO_SMSCECE + tristate SMSCECE 1099 I2C GPIO expander + depends on I2C + help + This option enables support for 18 GPIOs found + on SMSC ECE 1099 GPIO Expanders. + comment PCI GPIO expanders: config GPIO_CS5535 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 153cace..7c803c5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o obj-$(CONFIG_GPIO_AB8500)+= gpio-ab8500.o obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o +obj-$(CONFIG_GPIO_SMSCECE) += gpio-smscece.o obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o diff --git a/drivers/gpio/gpio-smscece.c b/drivers/gpio/gpio-smscece.c new file mode 100644 index 000..0cb0959 --- /dev/null +++ b/drivers/gpio/gpio-smscece.c @@ -0,0 +1,373 @@ +/* + * GPIO Chip driver for smsc + * SMSC I/O Expander and QWERTY Keypad Controller + * + * Copyright 2012 Texas Instruments Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include linux/module.h +#include linux/kernel.h +#include linux/slab.h +#include linux/init.h +#include linux/i2c.h +#include linux/gpio.h +#include linux/interrupt.h +#include linux/irqdomain.h +#include linux/irq.h +#include linux/mfd/smsc.h +#include linux/err.h + +struct smsc_gpio { + struct device *dev; + struct smsc *smsc; + struct gpio_chip gpio_chip; + struct mutex lock; /* protect cached dir, dat_out */ + /* protect serialized access to the interrupt controller bus */ + struct mutex irq_lock; + unsigned gpio_start; + int type; + int flags; + int irq; + int irq_base; + unsigned int gpio_base; + unsigned int dat_out[5]; + unsigned int dir[5]; + unsigned int int_lvl[5]; + unsigned int int_en[5]; + unsigned int irq_mask[5]; + unsigned int irq_stat[5]; +}; + +static int smsc_gpio_get_value(struct gpio_chip *chip, unsigned off) +{ + struct smsc_gpio *sg = + container_of(chip, struct smsc_gpio, gpio_chip); + unsigned int get; + return !!(smsc_read(sg-dev, + (SMSC_GPIO_DATA_IN_START + SMSC_BANK(off)) SMSC_BIT(off), + get)); +} + +static void smsc_gpio_set_value(struct gpio_chip *chip, + unsigned off, int val) +{ + unsigned bank, bit; + struct smsc_gpio *sg = + container_of(chip, struct smsc_gpio, gpio_chip); + + bank = SMSC_BANK(off); + bit = SMSC_BIT(off); + + mutex_lock(sg-lock); + if (val) + sg-dat_out[bank] |= bit; + else + sg-dat_out[bank] = ~bit; + + smsc_write(sg-dev, SMSC_GPIO_DATA_OUT_START + bank, +sg-dat_out[bank]); + mutex_unlock(sg-lock); +} + +static int smsc_gpio_direction_input(struct gpio_chip *chip, unsigned off) +{ + unsigned int reg; + struct smsc_gpio *sg = + container_of(chip, struct smsc_gpio, gpio_chip); + int reg_dir; + + mutex_lock(sg-lock); + reg_dir = SMSC_CFG_START + off; + smsc_read(sg-dev, reg_dir, reg); + reg |= SMSC_GPIO_INPUT_LOW; + mutex_unlock(sg-lock); + + return smsc_write(sg-dev, reg_dir, reg); +} + +static int smsc_gpio_direction_output(struct gpio_chip *chip, + unsigned off, int val) +{ + unsigned int reg; + struct smsc_gpio *sg = + container_of(chip, struct smsc_gpio, gpio_chip); + int reg_dir; + + mutex_lock(sg-lock); + reg_dir = SMSC_CFG_START + off; + smsc_read(sg-dev, reg_dir, reg); + reg |= SMSC_GPIO_OUTPUT_PP; + mutex_unlock(sg-lock); + + return smsc_write(sg-dev, reg_dir, reg); +} + +static int smsc_gpio_to_irq(struct gpio_chip *chip, unsigned off) +{ + struct
Re: [RFC/PATCH 10/13] serial: omap: stick to put_autosuspend
On Tue, Aug 21, 2012 at 04:12:11PM +0530, Shilimkar, Santosh wrote: On Tue, Aug 21, 2012 at 2:45 PM, Felipe Balbi ba...@ti.com wrote: Everytime we're done using our TTY, we want the pm timer to be reinitilized. By sticking to pm_runtime_pm_autosuspend() we make sure that this will always be the case. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 33 ++--- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 6ea24c5..458d77c 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -164,7 +164,8 @@ static void serial_omap_enable_ms(struct uart_port *port) pm_runtime_get_sync(up-dev); up-ier |= UART_IER_MSI; serial_out(up, UART_IER, up-ier); - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); } Can you please expand the change-log a bit ? Didn't follow the time re-init part completely. It's really just a micro-optimization. The thing is: if I call pm_runtime_put(), I will not reinitialize the pm timer to whatever timeout value I used. This means that pm_runtime_put() could actually execute right away (if timer was about to expire when I called pm_runtime_put()). While this wouldn't cause any issues, it's better to reinitialize the timer and make sure if there's another read/write/set_termios/whatever coming right after this, UART is still powered up. I mean, it's really just trying to avoid context save restore when UART is still under heavy usage. Does it make sense ? -- balbi signature.asc Description: Digital signature
Re: [RFC/PATCH 10/13] serial: omap: stick to put_autosuspend
On Tue, Aug 21, 2012 at 4:27 PM, Felipe Balbi ba...@ti.com wrote: On Tue, Aug 21, 2012 at 04:12:11PM +0530, Shilimkar, Santosh wrote: On Tue, Aug 21, 2012 at 2:45 PM, Felipe Balbi ba...@ti.com wrote: Everytime we're done using our TTY, we want the pm timer to be reinitilized. By sticking to pm_runtime_pm_autosuspend() we make sure that this will always be the case. Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/tty/serial/omap-serial.c | 33 ++--- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 6ea24c5..458d77c 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -164,7 +164,8 @@ static void serial_omap_enable_ms(struct uart_port *port) pm_runtime_get_sync(up-dev); up-ier |= UART_IER_MSI; serial_out(up, UART_IER, up-ier); - pm_runtime_put(up-dev); + pm_runtime_mark_last_busy(up-dev); + pm_runtime_put_autosuspend(up-dev); } Can you please expand the change-log a bit ? Didn't follow the time re-init part completely. It's really just a micro-optimization. The thing is: if I call pm_runtime_put(), I will not reinitialize the pm timer to whatever timeout value I used. This means that pm_runtime_put() could actually execute right away (if timer was about to expire when I called pm_runtime_put()). While this wouldn't cause any issues, it's better to reinitialize the timer and make sure if there's another read/write/set_termios/whatever coming right after this, UART is still powered up. I mean, it's really just trying to avoid context save restore when UART is still under heavy usage. Does it make sense ? It does. Would be good to add the above description in the change-log. Thanks for clarification. Regars Santosh -- To unsubscribe from this list: send the line unsubscribe linux-omap in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html