* [PATCH v4 07/10] ARM: dts: Add camera to node exynos4.dtsi
From: Sylwester Nawrocki @ 2013-02-01 19:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359745771-23684-1-git-send-email-s.nawrocki@samsung.com>
This patch adds common FIMC device nodes for all Exynos4 SoCs.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/boot/dts/exynos4.dtsi | 64 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index e1347fc..75c388b 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -36,6 +36,12 @@
i2c5 = &i2c_5;
i2c6 = &i2c_6;
i2c7 = &i2c_7;
+ csis0 = &csis_0;
+ csis1 = &csis_1;
+ fimc0 = &fimc_0;
+ fimc1 = &fimc_1;
+ fimc2 = &fimc_2;
+ fimc3 = &fimc_3;
};
pd_mfc: mfc-power-domain at 10023C40 {
@@ -82,6 +88,64 @@
reg = <0x10440000 0x1000>;
};
+ camera {
+ compatible = "samsung,fimc", "simple-bus";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ fimc_0: fimc at 11800000 {
+ compatible = "samsung,exynos4210-fimc";
+ reg = <0x11800000 0x1000>;
+ interrupts = <0 84 0>;
+ samsung,power-domain = <&pd_cam>;
+ status = "disabled";
+ };
+
+ fimc_1: fimc at 11810000 {
+ compatible = "samsung,exynos4210-fimc";
+ reg = <0x11810000 0x1000>;
+ interrupts = <0 85 0>;
+ samsung,power-domain = <&pd_cam>;
+ status = "disabled";
+ };
+
+ fimc_2: fimc at 11820000 {
+ compatible = "samsung,exynos4210-fimc";
+ reg = <0x11820000 0x1000>;
+ interrupts = <0 86 0>;
+ samsung,power-domain = <&pd_cam>;
+ status = "disabled";
+ };
+
+ fimc_3: fimc at 11830000 {
+ compatible = "samsung,exynos4210-fimc";
+ reg = <0x11830000 0x1000>;
+ interrupts = <0 87 0>;
+ samsung,power-domain = <&pd_cam>;
+ status = "disabled";
+ };
+
+ csis_0: csis at 11880000 {
+ compatible = "samsung,exynos4210-csis";
+ reg = <0x11880000 0x4000>;
+ interrupts = <0 78 0>;
+ bus-width = <4>;
+ samsung,power-domain = <&pd_cam>;
+ status = "disabled";
+ };
+
+ csis_1: csis at 11890000 {
+ compatible = "samsung,exynos4210-csis";
+ reg = <0x11890000 0x4000>;
+ interrupts = <0 80 0>;
+ bus-width = <2>;
+ samsung,power-domain = <&pd_cam>;
+ status = "disabled";
+ };
+ };
+
watchdog at 10060000 {
compatible = "samsung,s3c2410-wdt";
reg = <0x10060000 0x100>;
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 06/10] s5p-fimc: Use pinctrl API for camera ports configuration
From: Sylwester Nawrocki @ 2013-02-01 19:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359745771-23684-1-git-send-email-s.nawrocki@samsung.com>
Before the camera ports can be used the pinmux needs to be configured
properly. This patch adds a function to set the camera ports pinctrl
to a default state within the media driver's probe().
The camera port(s) are then configured for the video bus operation.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Changes since v3:
- removed the "inactive" pinctrl state, it will be added later if required
---
.../devicetree/bindings/media/soc/samsung-fimc.txt | 7 +++++++
drivers/media/platform/s5p-fimc/fimc-mdevice.c | 9 +++++++++
2 files changed, 16 insertions(+)
diff --git a/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
index 6b81ad1..3788305 100644
--- a/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
+++ b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
@@ -18,6 +18,10 @@ Required properties:
- compatible : must be "samsung,fimc", "simple-bus"
+- pinctrl-names : pinctrl names for camera port pinmux control, at least
+ "default" needs to be specified.
+- pinctrl-0...N : pinctrl properties corresponding to pinctrl-names
+
The 'camera' node must include at least one 'fimc' child node.
@@ -133,6 +137,9 @@ Example:
#size-cells = <1>;
status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&cam_port_a_clk_active>;
+
/* parallel camera ports */
parallel-ports {
/* camera A input */
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
index 2bb501f..6c2c9e3 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -21,6 +21,7 @@
#include <linux/of_platform.h>
#include <linux/of_device.h>
#include <linux/of_i2c.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/types.h>
@@ -1197,6 +1198,14 @@ static int fimc_md_probe(struct platform_device *pdev)
/* Protect the media graph while we're registering entities */
mutex_lock(&fmd->media_dev.graph_mutex);
+ if (dev->of_node) {
+ struct pinctrl *pctl = devm_pinctrl_get_select_default(dev);
+ if (IS_ERR(pctl)) {
+ ret = PTR_ERR(pctl);
+ goto err_unlock;
+ }
+ }
+
if (fmd->pdev->dev.of_node)
ret = fimc_md_register_of_platform_entities(fmd, dev->of_node);
else
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 05/10] s5p-fimc: Add device tree based sensors registration
From: Sylwester Nawrocki @ 2013-02-01 19:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359745771-23684-1-git-send-email-s.nawrocki@samsung.com>
The sensor (I2C and/or SPI client) devices are instantiated by their
corresponding control bus drivers. Since the I2C client's master clock
is often provided by a video bus receiver (host interface) or other
than I2C/SPI controller device, the drivers of those client devices
are not accessing hardware in their driver's probe() callback. Instead,
after enabling clock, the host driver calls back into a sub-device
when it wants to activate them. This pattern is used by some in-tree
drivers and this patch also uses it for DT case. This patch is intended
as a first step for adding device tree support to the S5P/Exynos SoC
camera drivers. The second one is adding support for asynchronous
sub-devices registration and clock control from sub-device driver
level. The bindings shall not change when asynchronous probing support
is added.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
.../devicetree/bindings/media/soc/samsung-fimc.txt | 89 ++++++++
drivers/media/platform/s5p-fimc/fimc-mdevice.c | 231 +++++++++++++++++---
include/media/s5p_fimc.h | 16 ++
3 files changed, 311 insertions(+), 25 deletions(-)
diff --git a/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
index 2b932f2..6b81ad1 100644
--- a/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
+++ b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
@@ -56,6 +56,29 @@ For every fimc-lite node a numbered alias should be present in the aliases
node. Aliases are in form of fimc-lite<n>, where <n> is an integer (0...N)
specifying the IP's instance index.
+
+'parallel-ports' node
+---------------------
+
+This node should contain child 'port' nodes specifying active parallel video
+input ports. It includes camera A and camera B inputs. 'reg' property in the
+port nodes specifies data input - 0, 1 indicates input A, B respectively.
+
+Optional properties
+
+- samsung,camclk-out : specifies clock output for remote sensor,
+ 0 - CAM_A_CLKOUT, 1 - CAM_B_CLKOUT;
+
+Image sensor nodes
+------------------
+
+The sensor device nodes should be added as their control bus controller
+(e.g. I2C0) child nodes and linked to a port node in the csis or parallel-ports
+node, using common the common video interfaces bindings, i.e. port/endpoint
+node pairs. The implementation of this binding requires clock-frequency
+property to be present in the sensor device nodes.
+
+
Example:
aliases {
@@ -63,12 +86,68 @@ Example:
fimc0 = &fimc_0;
};
+ /* Parallel bus IF sensor */
+ i2c_0: i2c at 13860000 {
+ s5k6aa: sensor at 3c {
+ compatible = "samsung,s5k6aafx";
+ reg = <0x3c>;
+ vddio-supply = <...>;
+
+ clock-frequency = <24000000>;
+ clocks = <...>;
+ clock-names = "mclk";
+
+ port {
+ s5k6aa_ep: endpoint {
+ remote-endpoint = <&fimc0_ep>;
+ bus-width = <8>;
+ hsync-active = <0>;
+ hsync-active = <1>;
+ pclk-sample = <1>;
+ };
+ };
+ };
+ };
+
+ /* MIPI CSI-2 bus IF sensor */
+ s5c73m3: sensor at 0x1a {
+ compatible = "samsung,s5c73m3";
+ reg = <0x1a>;
+ vddio-supply = <...>;
+
+ clock-frequency = <24000000>;
+ clocks = <...>;
+ clock-names = "mclk";
+
+ port {
+ s5c73m3_1: endpoint {
+ data-lanes = <1>, <2>, <3>, <4>;
+ remote-endpoint = <&csis0_ep>;
+ };
+ };
+ };
+
camera {
compatible = "samsung,fimc", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
status = "okay";
+ /* parallel camera ports */
+ parallel-ports {
+ /* camera A input */
+ port at 0 {
+ reg = <1>;
+ fimc0_ep: endpoint {
+ remote-endpoint = <&s5k6aa_ep>;
+ bus-width = <8>;
+ hsync-active = <0>;
+ hsync-active = <1>;
+ pclk-sample = <1>;
+ };
+ };
+ };
+
fimc_0: fimc at 11800000 {
compatible = "samsung,exynos4210-fimc";
reg = <0x11800000 0x1000>;
@@ -81,6 +160,16 @@ Example:
reg = <0x11880000 0x1000>;
interrupts = <0 78 0>;
max-data-lanes = <4>;
+ /* camera C input */
+ port {
+ reg = <3>;
+ csis0_ep: endpoint {
+ remote-endpoint = <&s5c73m3_ep>;
+ data-lanes = <1>, <2>, <3>, <4>;
+ samsung,csis-hs-settle = <12>;
+ samsung,camclk-out = <0>;
+ };
+ };
};
};
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
index c113734..2bb501f 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -19,11 +19,14 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/of_i2c.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <media/v4l2-ctrls.h>
+#include <media/v4l2-of.h>
#include <media/media-device.h>
#include <media/s5p_fimc.h>
@@ -248,7 +251,7 @@ static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
sd->grp_id = GRP_ID_SENSOR;
v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
- s_info->pdata.board_info->type);
+ sd->name);
return sd;
}
@@ -260,17 +263,185 @@ static void fimc_md_unregister_sensor(struct v4l2_subdev *sd)
if (!client)
return;
v4l2_device_unregister_subdev(sd);
- adapter = client->adapter;
- i2c_unregister_device(client);
- if (adapter)
- i2c_put_adapter(adapter);
+
+ if (!client->dev.of_node) {
+ adapter = client->adapter;
+ i2c_unregister_device(client);
+ if (adapter)
+ i2c_put_adapter(adapter);
+ }
+}
+
+#ifdef CONFIG_OF
+/* Register I2C client subdev associated with @node. */
+static int fimc_md_of_add_sensor(struct fimc_md *fmd,
+ struct device_node *node, int index)
+{
+ struct fimc_sensor_info *si;
+ struct i2c_client *client;
+ struct v4l2_subdev *sd;
+ int ret;
+
+ if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor)))
+ return -EINVAL;
+ si = &fmd->sensor[index];
+
+ client = of_find_i2c_device_by_node(node);
+ if (!client)
+ return -EPROBE_DEFER;
+
+ device_lock(&client->dev);
+
+ if (!client->driver ||
+ !try_module_get(client->driver->driver.owner)) {
+ ret = -EPROBE_DEFER;
+ goto dev_put;
+ }
+
+ /* Enable sensor's master clock */
+ ret = __fimc_md_set_camclk(fmd, si, true);
+ if (ret < 0)
+ goto mod_put;
+ sd = i2c_get_clientdata(client);
+
+ ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
+ __fimc_md_set_camclk(fmd, si, false);
+ if (ret < 0)
+ goto mod_put;
+
+ v4l2_set_subdev_hostdata(sd, si);
+ sd->grp_id = GRP_ID_SENSOR;
+ si->subdev = sd;
+ v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice: %s (%d)\n",
+ sd->name, fmd->num_sensors);
+ fmd->num_sensors++;
+
+mod_put:
+ module_put(client->driver->driver.owner);
+dev_put:
+ device_unlock(&client->dev);
+ put_device(&client->dev);
+ return ret;
}
+/* Parse port node and register as a sub-device any sensor specified there. */
+static int fimc_md_parse_port_node(struct fimc_md *fmd,
+ struct device_node *port,
+ unsigned int index)
+{
+ struct device_node *rem, *endpoint;
+ struct fimc_source_info *pd;
+ struct v4l2_of_endpoint bus_cfg;
+ u32 tmp, reg = 0;
+ int ret;
+
+ if (WARN_ON(of_property_read_u32(port, "reg", ®) ||
+ reg >= FIMC_MAX_SENSORS))
+ return -EINVAL;
+
+ pd = &fmd->sensor[index].pdata;
+ pd->mux_id = (reg - 1) & 0x1;
+
+ /* Assume here a port node can have only one endpoint node. */
+ endpoint = of_get_next_child(port, NULL);
+ if (!endpoint)
+ return 0;
+
+ rem = v4l2_of_get_remote_port_parent(endpoint);
+ of_node_put(endpoint);
+ if (rem == NULL) {
+ v4l2_info(&fmd->v4l2_dev, "Remote device at %s not found\n",
+ endpoint->full_name);
+ return 0;
+ }
+ if (!of_property_read_u32(rem, "samsung,camclk-out", &tmp))
+ pd->clk_id = tmp;
+
+ if (!of_property_read_u32(rem, "clock-frequency", &tmp))
+ pd->clk_frequency = tmp;
+
+ if (pd->clk_frequency == 0) {
+ v4l2_err(&fmd->v4l2_dev, "Wrong clock frequency at node %s\n",
+ rem->full_name);
+ of_node_put(rem);
+ return -EINVAL;
+ }
+
+ if (fimc_input_is_parallel(reg)) {
+ v4l2_of_parse_parallel_bus(endpoint, &bus_cfg);
+ if (bus_cfg.mbus.type == V4L2_MBUS_PARALLEL)
+ pd->sensor_bus_type = FIMC_BUS_TYPE_ITU_601;
+ else
+ pd->sensor_bus_type = FIMC_BUS_TYPE_ITU_656;
+ pd->flags = bus_cfg.mbus.flags;
+ } else if (fimc_input_is_mipi_csi(reg)) {
+ /*
+ * MIPI CSI-2: only input mux selection
+ * and sensor's clock frequency is needed.
+ */
+ pd->sensor_bus_type = FIMC_BUS_TYPE_MIPI_CSI2;
+ } else {
+ v4l2_err(&fmd->v4l2_dev, "Wrong port id (%u) at node %s\n",
+ reg, rem->full_name);
+ }
+
+ ret = fimc_md_of_add_sensor(fmd, rem, index);
+ of_node_put(rem);
+
+ return ret;
+}
+
+/* Register all SoC external sub-devices */
+static int fimc_md_of_sensors_register(struct fimc_md *fmd,
+ struct device_node *np)
+{
+ struct device_node *parent = fmd->pdev->dev.of_node;
+ struct device_node *node, *ports;
+ int index = 0;
+ int ret;
+
+ /* Attach sensors linked to MIPI CSI-2 receivers */
+ for_each_available_child_of_node(parent, node) {
+ struct device_node *port;
+
+ if (of_node_cmp(node->name, "csis"))
+ continue;
+ /* The csis node can have only port subnode. */
+ port = of_get_next_child(node, NULL);
+ if (!port)
+ continue;
+
+ ret = fimc_md_parse_port_node(fmd, port, index);
+ if (ret < 0)
+ return ret;
+ index++;
+ }
+
+ /* Attach sensors listed in the parallel-ports node */
+ ports = of_get_child_by_name(parent, "parallel-ports");
+ if (!ports)
+ return 0;
+
+ for_each_child_of_node(ports, node) {
+ ret = fimc_md_parse_port_node(fmd, node, index);
+ if (ret < 0)
+ break;
+ index++;
+ }
+
+ return 0;
+}
+#else
+#define fimc_md_of_sensors_register(fmd, np) (-ENOSYS)
+#endif
+
static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
{
struct s5p_platform_fimc *pdata = fmd->pdev->dev.platform_data;
+ struct device_node *of_node = fmd->pdev->dev.of_node;
struct fimc_dev *fd = NULL;
- int num_clients, ret, i;
+ int num_clients = 0;
+ int ret, i;
/*
* Runtime resume one of the FIMC entities to make sure
@@ -281,34 +452,42 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
fd = fmd->fimc[i];
if (!fd)
return -ENXIO;
+
ret = pm_runtime_get_sync(&fd->pdev->dev);
if (ret < 0)
return ret;
- WARN_ON(pdata->num_clients > ARRAY_SIZE(fmd->sensor));
- num_clients = min_t(u32, pdata->num_clients, ARRAY_SIZE(fmd->sensor));
+ if (of_node) {
+ fmd->num_sensors = 0;
+ ret = fimc_md_of_sensors_register(fmd, of_node);
+ } else if (pdata) {
+ WARN_ON(pdata->num_clients > ARRAY_SIZE(fmd->sensor));
+ num_clients = min_t(u32, pdata->num_clients,
+ ARRAY_SIZE(fmd->sensor));
+ fmd->num_sensors = num_clients;
fmd->num_sensors = num_clients;
for (i = 0; i < num_clients; i++) {
struct v4l2_subdev *sd;
- fmd->sensor[i].pdata = pdata->source_info[i];
- ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true);
- if (ret)
- break;
- sd = fimc_md_register_sensor(fmd, &fmd->sensor[i]);
- ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], false);
+ fmd->sensor[i].pdata = pdata->source_info[i];
+ ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true);
+ if (ret)
+ break;
+ sd = fimc_md_register_sensor(fmd, &fmd->sensor[i]);
+ ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], false);
- if (!IS_ERR(sd)) {
+ if (IS_ERR(sd)) {
+ fmd->sensor[i].subdev = NULL;
+ ret = PTR_ERR(sd);
+ break;
+ }
fmd->sensor[i].subdev = sd;
- } else {
- fmd->sensor[i].subdev = NULL;
- ret = PTR_ERR(sd);
- break;
+ if (ret)
+ break;
}
- if (ret)
- break;
}
+
pm_runtime_put(&fd->pdev->dev);
return ret;
}
@@ -976,11 +1155,12 @@ static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
static int fimc_md_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
struct v4l2_device *v4l2_dev;
struct fimc_md *fmd;
int ret;
- fmd = devm_kzalloc(&pdev->dev, sizeof(*fmd), GFP_KERNEL);
+ fmd = devm_kzalloc(dev, sizeof(*fmd), GFP_KERNEL);
if (!fmd)
return -ENOMEM;
@@ -990,7 +1170,7 @@ static int fimc_md_probe(struct platform_device *pdev)
strlcpy(fmd->media_dev.model, "SAMSUNG S5P FIMC",
sizeof(fmd->media_dev.model));
fmd->media_dev.link_notify = fimc_md_link_notify;
- fmd->media_dev.dev = &pdev->dev;
+ fmd->media_dev.dev = dev;
v4l2_dev = &fmd->v4l2_dev;
v4l2_dev->mdev = &fmd->media_dev;
@@ -998,7 +1178,7 @@ static int fimc_md_probe(struct platform_device *pdev)
strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));
- ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev);
+ ret = v4l2_device_register(dev, &fmd->v4l2_dev);
if (ret < 0) {
v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
return ret;
@@ -1025,11 +1205,12 @@ static int fimc_md_probe(struct platform_device *pdev)
if (ret)
goto err_unlock;
- if (pdev->dev.platform_data) {
+ if (dev->platform_data || dev->of_node) {
ret = fimc_md_register_sensor_entities(fmd);
if (ret)
goto err_unlock;
}
+
ret = fimc_md_create_links(fmd);
if (ret)
goto err_unlock;
diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h
index 17fd2fa..e2434bb 100644
--- a/include/media/s5p_fimc.h
+++ b/include/media/s5p_fimc.h
@@ -15,6 +15,19 @@
#include <media/media-entity.h>
/*
+ * Enumeration of data inputs to the camera subsystem.
+ */
+enum fimc_input {
+ FIMC_INPUT_PARALLEL_0 = 1,
+ FIMC_INPUT_PARALLEL_1,
+ FIMC_INPUT_MIPI_CSI2_0 = 3,
+ FIMC_INPUT_MIPI_CSI2_1,
+ FIMC_INPUT_WRITEBACK_A = 5,
+ FIMC_INPUT_WRITEBACK_B,
+ FIMC_INPUT_WRITEBACK_ISP = 5,
+};
+
+/*
* Enumeration of the FIMC data bus types.
*/
enum fimc_bus_type {
@@ -32,6 +45,9 @@ enum fimc_bus_type {
FIMC_BUS_TYPE_ISP_WRITEBACK = FIMC_BUS_TYPE_LCD_WRITEBACK_B,
};
+#define fimc_input_is_parallel(x) ((x) == 1 || (x) == 2)
+#define fimc_input_is_mipi_csi(x) ((x) == 3 || (x) == 4)
+
struct i2c_board_info;
/**
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 04/10] s5p-fimc: Add device tree support for the main media device driver
From: Sylwester Nawrocki @ 2013-02-01 19:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359745771-23684-1-git-send-email-s.nawrocki@samsung.com>
This patch adds changes required for the main camera media device
driver to be initialized on systems instantiated from the device tree.
The platform devices corresponding to child nodes of the 'camera'
node are looked up and and registered as sub-devices to the common
media device. The main driver's probing is deferred if any of the
sub-device drivers is not yet initialized and ready.
An OF matching table is added for the main driver associated with
the 'camera' node.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/platform/s5p-fimc/fimc-core.c | 1 -
drivers/media/platform/s5p-fimc/fimc-mdevice.c | 77 +++++++++++++++++++++---
drivers/media/platform/s5p-fimc/fimc-mdevice.h | 4 ++
include/media/s5p_fimc.h | 1 +
4 files changed, 75 insertions(+), 8 deletions(-)
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.c b/drivers/media/platform/s5p-fimc/fimc-core.c
index 07ca0e0..ba743a5 100644
--- a/drivers/media/platform/s5p-fimc/fimc-core.c
+++ b/drivers/media/platform/s5p-fimc/fimc-core.c
@@ -1276,7 +1276,6 @@ static const struct platform_device_id fimc_driver_ids[] = {
},
{ },
};
-MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
static const struct of_device_id fimc_of_match[] = {
{
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
index f49f6f1..c113734 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -17,6 +17,8 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/types.h>
@@ -457,6 +459,51 @@ static int fimc_md_pdev_match(struct device *dev, void *data)
return 0;
}
+/* Register FIMC, FIMC-LITE and CSIS media entities */
+#ifdef CONFIG_OF
+static int fimc_md_register_of_platform_entities(struct fimc_md *fmd,
+ struct device_node *parent)
+{
+ struct device_node *node;
+ int ret = 0;
+
+ for_each_available_child_of_node(parent, node) {
+ struct platform_device *pdev;
+ int plat_entity = -1;
+
+ pdev = of_find_device_by_node(node);
+ if (!pdev)
+ continue;
+
+ /* If driver of any entity isn't ready try all again later. */
+ if (!strcmp(node->name, CSIS_OF_NODE_NAME))
+ plat_entity = IDX_CSIS;
+ else if (!strcmp(node->name, FIMC_LITE_OF_NODE_NAME))
+ plat_entity = IDX_FLITE;
+ else if (!strcmp(node->name, FIMC_OF_NODE_NAME))
+ plat_entity = IDX_FIMC;
+
+ if (plat_entity >= 0)
+ ret = fimc_md_register_platform_entity(fmd, pdev,
+ plat_entity);
+ put_device(&pdev->dev);
+ if (ret < 0)
+ break;
+
+ /* FIMC-IS child devices */
+ if (plat_entity == IDX_IS_ISP) {
+ ret = fimc_md_register_of_platform_entities(fmd, node);
+ if (ret < 0)
+ break;
+ }
+ }
+
+ return ret;
+}
+#else
+#define fimc_md_register_platform_entities(fmd) (-ENOSYS)
+#endif
+
static void fimc_md_unregister_entities(struct fimc_md *fmd)
{
int i;
@@ -948,8 +995,8 @@ static int fimc_md_probe(struct platform_device *pdev)
v4l2_dev = &fmd->v4l2_dev;
v4l2_dev->mdev = &fmd->media_dev;
v4l2_dev->notify = fimc_sensor_notify;
- snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s",
- dev_name(&pdev->dev));
+ strlcpy(v4l2_dev->name, "s5p-fimc-md", sizeof(v4l2_dev->name));
+
ret = v4l2_device_register(&pdev->dev, &fmd->v4l2_dev);
if (ret < 0) {
@@ -965,13 +1012,16 @@ static int fimc_md_probe(struct platform_device *pdev)
if (ret)
goto err_clk;
- fmd->user_subdev_api = false;
+ fmd->user_subdev_api = (dev->of_node != NULL);
/* Protect the media graph while we're registering entities */
mutex_lock(&fmd->media_dev.graph_mutex);
- ret = bus_for_each_dev(&platform_bus_type, NULL, fmd,
- fimc_md_pdev_match);
+ if (fmd->pdev->dev.of_node)
+ ret = fimc_md_register_of_platform_entities(fmd, dev->of_node);
+ else
+ ret = bus_for_each_dev(&platform_bus_type, NULL, fmd,
+ fimc_md_pdev_match);
if (ret)
goto err_unlock;
@@ -1019,12 +1069,25 @@ static int fimc_md_remove(struct platform_device *pdev)
return 0;
}
+static struct platform_device_id fimc_driver_ids[] __always_unused = {
+ { .name = "s5p-fimc-md" },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
+
+static const struct of_device_id fimc_md_of_match[] __initconst = {
+ { .compatible = "samsung,fimc" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, fimc_md_of_match);
+
static struct platform_driver fimc_md_driver = {
.probe = fimc_md_probe,
.remove = fimc_md_remove,
.driver = {
- .name = "s5p-fimc-md",
- .owner = THIS_MODULE,
+ .of_match_table = fimc_md_of_match,
+ .name = "s5p-fimc-md",
+ .owner = THIS_MODULE,
}
};
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.h b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
index 06b0d82..f3e0251 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.h
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
@@ -21,6 +21,10 @@
#include "fimc-lite.h"
#include "mipi-csis.h"
+#define FIMC_OF_NODE_NAME "fimc"
+#define FIMC_LITE_OF_NODE_NAME "fimc-lite"
+#define CSIS_OF_NODE_NAME "csis"
+
/* Group IDs of sensor, MIPI-CSIS, FIMC-LITE and the writeback subdevs. */
#define GRP_ID_SENSOR (1 << 8)
#define GRP_ID_FIMC_IS_SENSOR (1 << 9)
diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h
index 28f3590..17fd2fa 100644
--- a/include/media/s5p_fimc.h
+++ b/include/media/s5p_fimc.h
@@ -81,6 +81,7 @@ enum fimc_subdev_index {
IDX_SENSOR,
IDX_CSIS,
IDX_FLITE,
+ IDX_IS_ISP,
IDX_FIMC,
IDX_MAX,
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 03/10] s5p-fimc: Add device tree support for FIMC-LITE devices
From: Sylwester Nawrocki @ 2013-02-01 19:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359745771-23684-1-git-send-email-s.nawrocki@samsung.com>
This patch add support for binding the driver to FIMC-LITE devices
instantiated from the device tree.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
.../devicetree/bindings/media/soc/samsung-fimc.txt | 15 +++++
drivers/media/platform/s5p-fimc/fimc-lite.c | 65 ++++++++++++++------
2 files changed, 61 insertions(+), 19 deletions(-)
diff --git a/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
index 916b2c3..2b932f2 100644
--- a/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
+++ b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
@@ -41,6 +41,21 @@ Optional properties
- clock-frequency - maximum FIMC local clock (LCLK) frequency
+'fimc-lite' device nodes
+-----------------------
+
+Required properties:
+
+- compatible : should be "samsung,exynos4212-fimc" for Exynos4212 and
+ Exynos4412 SoCs;
+- reg : physical base address and size of the device memory mapped
+ registers;
+- interrupts : should contain FIMC-LITE interrupt;
+
+For every fimc-lite node a numbered alias should be present in the aliases
+node. Aliases are in form of fimc-lite<n>, where <n> is an integer (0...N)
+specifying the IP's instance index.
+
Example:
aliases {
diff --git a/drivers/media/platform/s5p-fimc/fimc-lite.c b/drivers/media/platform/s5p-fimc/fimc-lite.c
index e18babf..a0a70bc 100644
--- a/drivers/media/platform/s5p-fimc/fimc-lite.c
+++ b/drivers/media/platform/s5p-fimc/fimc-lite.c
@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -1480,18 +1481,34 @@ static int fimc_lite_clk_get(struct fimc_lite *fimc)
return ret;
}
+static const struct of_device_id flite_of_match[];
+
static int fimc_lite_probe(struct platform_device *pdev)
{
- struct flite_drvdata *drv_data = fimc_lite_get_drvdata(pdev);
+ struct flite_drvdata *drv_data = NULL;
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *of_id;
struct fimc_lite *fimc;
struct resource *res;
int ret;
- fimc = devm_kzalloc(&pdev->dev, sizeof(*fimc), GFP_KERNEL);
+ fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL);
if (!fimc)
return -ENOMEM;
- fimc->index = pdev->id;
+ if (dev->of_node) {
+ of_id = of_match_node(flite_of_match, dev->of_node);
+ if (of_id)
+ drv_data = (struct flite_drvdata *)of_id->data;
+ fimc->index = of_alias_get_id(dev->of_node, "fimc-lite");
+ } else {
+ drv_data = fimc_lite_get_drvdata(pdev);
+ fimc->index = pdev->id;
+ }
+
+ if (!drv_data || fimc->index < 0 || fimc->index >= FIMC_LITE_MAX_DEVS)
+ return -EINVAL;
+
fimc->variant = drv_data->variant[fimc->index];
fimc->pdev = pdev;
@@ -1500,15 +1517,15 @@ static int fimc_lite_probe(struct platform_device *pdev)
mutex_init(&fimc->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- fimc->regs = devm_request_and_ioremap(&pdev->dev, res);
+ fimc->regs = devm_request_and_ioremap(dev, res);
if (fimc->regs == NULL) {
- dev_err(&pdev->dev, "Failed to obtain io memory\n");
+ dev_err(dev, "Failed to obtain io memory\n");
return -ENOENT;
}
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res == NULL) {
- dev_err(&pdev->dev, "Failed to get IRQ resource\n");
+ dev_err(dev, "Failed to get IRQ resource\n");
return -ENXIO;
}
@@ -1516,10 +1533,10 @@ static int fimc_lite_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = devm_request_irq(&pdev->dev, res->start, flite_irq_handler,
- 0, dev_name(&pdev->dev), fimc);
+ ret = devm_request_irq(dev, res->start, flite_irq_handler,
+ 0, dev_name(dev), fimc);
if (ret) {
- dev_err(&pdev->dev, "Failed to install irq (%d)\n", ret);
+ dev_err(dev, "Failed to install irq (%d)\n", ret);
goto err_clk;
}
@@ -1529,23 +1546,23 @@ static int fimc_lite_probe(struct platform_device *pdev)
goto err_clk;
platform_set_drvdata(pdev, fimc);
- pm_runtime_enable(&pdev->dev);
- ret = pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_enable(dev);
+ ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto err_sd;
- fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+ fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
if (IS_ERR(fimc->alloc_ctx)) {
ret = PTR_ERR(fimc->alloc_ctx);
goto err_pm;
}
- pm_runtime_put(&pdev->dev);
+ pm_runtime_put(dev);
- dev_dbg(&pdev->dev, "FIMC-LITE.%d registered successfully\n",
+ dev_dbg(dev, "FIMC-LITE.%d registered successfully\n",
fimc->index);
return 0;
err_pm:
- pm_runtime_put(&pdev->dev);
+ pm_runtime_put(dev);
err_sd:
fimc_lite_unregister_capture_subdev(fimc);
err_clk:
@@ -1636,6 +1653,12 @@ static int fimc_lite_remove(struct platform_device *pdev)
return 0;
}
+static const struct dev_pm_ops fimc_lite_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(fimc_lite_suspend, fimc_lite_resume)
+ SET_RUNTIME_PM_OPS(fimc_lite_runtime_suspend, fimc_lite_runtime_resume,
+ NULL)
+};
+
static struct flite_variant fimc_lite0_variant_exynos4 = {
.max_width = 8192,
.max_height = 8192,
@@ -1661,17 +1684,21 @@ static struct platform_device_id fimc_lite_driver_ids[] = {
};
MODULE_DEVICE_TABLE(platform, fimc_lite_driver_ids);
-static const struct dev_pm_ops fimc_lite_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(fimc_lite_suspend, fimc_lite_resume)
- SET_RUNTIME_PM_OPS(fimc_lite_runtime_suspend, fimc_lite_runtime_resume,
- NULL)
+static const struct of_device_id flite_of_match[] = {
+ {
+ .compatible = "samsung,exynos4212-fimc-lite",
+ .data = &fimc_lite_drvdata_exynos4,
+ },
+ { /* sentinel */ },
};
+MODULE_DEVICE_TABLE(of, flite_of_match);
static struct platform_driver fimc_lite_driver = {
.probe = fimc_lite_probe,
.remove = fimc_lite_remove,
.id_table = fimc_lite_driver_ids,
.driver = {
+ .of_match_table = flite_of_match,
.name = FIMC_LITE_DRV_NAME,
.owner = THIS_MODULE,
.pm = &fimc_lite_pm_ops,
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 02/10] s5p-fimc: Add device tree support for FIMC devices
From: Sylwester Nawrocki @ 2013-02-01 19:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359745771-23684-1-git-send-email-s.nawrocki@samsung.com>
This patch adds support for FIMC devices instantiated from devicetree
for S5PV210 and Exynos4 SoCs. The FIMC IP features include colorspace
conversion and scaling (mem-to-mem) and parallel/MIPI CSI2 bus video
capture interface.
Multiple SoC revisions specific parameters are defined statically in
the driver and are used for both dt and non-dt. The driver's static
data is selected based on the compatible property. Previously the
platform device name was used to match driver data and a specific
SoC/IP version.
Aliases are used to determine an index of the IP which is essential
for linking FIMC IP with other entities, like MIPI-CSIS (the MIPI
CSI-2 bus frontend) or FIMC-LITE and FIMC-IS ISP.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Changes since v3:
- added optional clock-frequency property to specify local bus
(FIMCn_LCLK) clock frequency
---
.../devicetree/bindings/media/soc/samsung-fimc.txt | 72 +++++++++++++++
drivers/media/platform/s5p-fimc/fimc-capture.c | 2 +-
drivers/media/platform/s5p-fimc/fimc-core.c | 93 +++++++++++++-------
3 files changed, 135 insertions(+), 32 deletions(-)
create mode 100644 Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
diff --git a/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
new file mode 100644
index 0000000..916b2c3
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
@@ -0,0 +1,72 @@
+Samsung S5P/EXYNOS SoC Camera Subsystem (FIMC)
+----------------------------------------------
+
+The Exynos Camera subsystem comprises of multiple sub-devices that are
+represented by separate platform devices. Some of the IPs come in different
+variants across the SoC revisions (FIMC) and some remain mostly unchanged
+(MIPI CSIS, FIMC-LITE).
+
+All those sub-subdevices are defined as parent nodes of the common device
+node, which also includes common properties of the whole subsystem not really
+specific to any single sub-device, like common camera port pins or external
+clocks for image sensors attached to the SoC.
+
+Common 'camera' node
+--------------------
+
+Required properties:
+
+- compatible : must be "samsung,fimc", "simple-bus"
+
+The 'camera' node must include at least one 'fimc' child node.
+
+
+'fimc' device nodes
+-------------------
+
+Required properties:
+
+- compatible : "samsung,s5pv210-fimc" for S5PV210,
+ "samsung,exynos4210-fimc" for Exynos4210,
+ "samsung,exynos4212-fimc" for Exynos4212/4412 SoCs;
+- reg : physical base address and size of the device memory mapped
+ registers;
+- interrupts : FIMC interrupt to the CPU should be described here;
+
+For every fimc node a numbered alias should be present in the aliases node.
+Aliases are of the form fimc<n>, where <n> is an integer (0...N) specifying
+the IP's instance index.
+
+Optional properties
+
+ - clock-frequency - maximum FIMC local clock (LCLK) frequency
+
+Example:
+
+ aliases {
+ csis0 = &csis_0;
+ fimc0 = &fimc_0;
+ };
+
+ camera {
+ compatible = "samsung,fimc", "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "okay";
+
+ fimc_0: fimc at 11800000 {
+ compatible = "samsung,exynos4210-fimc";
+ reg = <0x11800000 0x1000>;
+ interrupts = <0 85 0>;
+ status = "okay";
+ };
+
+ csis_0: csis at 11880000 {
+ compatible = "samsung,exynos4210-csis";
+ reg = <0x11880000 0x1000>;
+ interrupts = <0 78 0>;
+ max-data-lanes = <4>;
+ };
+ };
+
+[1] Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt
diff --git a/drivers/media/platform/s5p-fimc/fimc-capture.c b/drivers/media/platform/s5p-fimc/fimc-capture.c
index f822b8e..bc84301 100644
--- a/drivers/media/platform/s5p-fimc/fimc-capture.c
+++ b/drivers/media/platform/s5p-fimc/fimc-capture.c
@@ -1883,7 +1883,7 @@ int fimc_initialize_capture_subdev(struct fimc_dev *fimc)
v4l2_subdev_init(sd, &fimc_subdev_ops);
sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
- snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->pdev->id);
+ snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->id);
fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.c b/drivers/media/platform/s5p-fimc/fimc-core.c
index 29f7bb7..07ca0e0 100644
--- a/drivers/media/platform/s5p-fimc/fimc-core.c
+++ b/drivers/media/platform/s5p-fimc/fimc-core.c
@@ -21,6 +21,8 @@
#include <linux/pm_runtime.h>
#include <linux/list.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <media/v4l2-ioctl.h>
@@ -863,45 +865,57 @@ static int fimc_m2m_resume(struct fimc_dev *fimc)
return 0;
}
+static const struct of_device_id fimc_of_match[];
+
static int fimc_probe(struct platform_device *pdev)
{
- const struct fimc_drvdata *drv_data = fimc_get_drvdata(pdev);
- struct s5p_platform_fimc *pdata;
+ struct fimc_drvdata *drv_data = NULL;
+ struct device *dev = &pdev->dev;
+ const struct of_device_id *of_id;
+ u32 lclk_freq = 0;
struct fimc_dev *fimc;
struct resource *res;
int ret = 0;
- if (pdev->id >= drv_data->num_entities) {
- dev_err(&pdev->dev, "Invalid platform device id: %d\n",
- pdev->id);
- return -EINVAL;
- }
-
- fimc = devm_kzalloc(&pdev->dev, sizeof(*fimc), GFP_KERNEL);
+ fimc = devm_kzalloc(dev, sizeof(*fimc), GFP_KERNEL);
if (!fimc)
return -ENOMEM;
- fimc->id = pdev->id;
+ if (dev->of_node) {
+ of_id = of_match_node(fimc_of_match, dev->of_node);
+ if (of_id)
+ drv_data = (struct fimc_drvdata *)of_id->data;
+ fimc->id = of_alias_get_id(dev->of_node, "fimc");
+
+ of_property_read_u32(dev->of_node, "clock-frequency",
+ &lclk_freq);
+ } else {
+ drv_data = fimc_get_drvdata(pdev);
+ fimc->id = pdev->id;
+ }
+
+ if (!drv_data || fimc->id < 0 || fimc->id >= drv_data->num_entities) {
+ dev_err(dev, "Invalid driver data or device index (%d)\n",
+ fimc->id);
+ return -EINVAL;
+ }
fimc->variant = drv_data->variant[fimc->id];
fimc->pdev = pdev;
- pdata = pdev->dev.platform_data;
- fimc->pdata = pdata;
-
init_waitqueue_head(&fimc->irq_queue);
spin_lock_init(&fimc->slock);
mutex_init(&fimc->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- fimc->regs = devm_request_and_ioremap(&pdev->dev, res);
+ fimc->regs = devm_request_and_ioremap(dev, res);
if (fimc->regs == NULL) {
- dev_err(&pdev->dev, "Failed to obtain io memory\n");
+ dev_err(dev, "Failed to obtain io memory\n");
return -ENOENT;
}
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res == NULL) {
- dev_err(&pdev->dev, "Failed to get IRQ resource\n");
+ dev_err(dev, "Failed to get IRQ resource\n");
return -ENXIO;
}
@@ -909,7 +923,10 @@ static int fimc_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency);
+ if (lclk_freq == 0)
+ lclk_freq = drv_data->lclk_frequency;
+
+ ret = clk_set_rate(fimc->clock[CLK_BUS], lclk_freq);
if (ret < 0)
return ret;
@@ -917,10 +934,10 @@ static int fimc_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- ret = devm_request_irq(&pdev->dev, res->start, fimc_irq_handler,
- 0, dev_name(&pdev->dev), fimc);
+ ret = devm_request_irq(dev, res->start, fimc_irq_handler,
+ 0, dev_name(dev), fimc);
if (ret) {
- dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
+ dev_err(dev, "failed to install irq (%d)\n", ret);
goto err_clk;
}
@@ -929,27 +946,26 @@ static int fimc_probe(struct platform_device *pdev)
goto err_clk;
platform_set_drvdata(pdev, fimc);
- pm_runtime_enable(&pdev->dev);
- ret = pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_enable(dev);
+ ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto err_sd;
/* Initialize contiguous memory allocator */
- fimc->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+ fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
if (IS_ERR(fimc->alloc_ctx)) {
ret = PTR_ERR(fimc->alloc_ctx);
goto err_pm;
}
- dev_dbg(&pdev->dev, "FIMC.%d registered successfully\n", fimc->id);
+ dev_dbg(dev, "FIMC.%d registered successfully\n", fimc->id);
- pm_runtime_put(&pdev->dev);
+ pm_runtime_put(dev);
return 0;
err_pm:
- pm_runtime_put(&pdev->dev);
+ pm_runtime_put(dev);
err_sd:
fimc_unregister_capture_subdev(fimc);
err_clk:
- clk_disable(fimc->clock[CLK_BUS]);
fimc_clk_put(fimc);
return ret;
}
@@ -1258,10 +1274,24 @@ static const struct platform_device_id fimc_driver_ids[] = {
.name = "exynos4x12-fimc",
.driver_data = (unsigned long)&fimc_drvdata_exynos4x12,
},
- {},
+ { },
};
MODULE_DEVICE_TABLE(platform, fimc_driver_ids);
+static const struct of_device_id fimc_of_match[] = {
+ {
+ .compatible = "samsung,s5pv210-fimc",
+ .data = &fimc_drvdata_s5pv210,
+ }, {
+ .compatible = "samsung,exynos4210-fimc",
+ .data = &fimc_drvdata_exynos4210,
+ }, {
+ .compatible = "samsung,exynos4212-fimc",
+ .data = &fimc_drvdata_exynos4x12,
+ },
+ { /* sentinel */ },
+};
+
static const struct dev_pm_ops fimc_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(fimc_suspend, fimc_resume)
SET_RUNTIME_PM_OPS(fimc_runtime_suspend, fimc_runtime_resume, NULL)
@@ -1272,9 +1302,10 @@ static struct platform_driver fimc_driver = {
.remove = fimc_remove,
.id_table = fimc_driver_ids,
.driver = {
- .name = FIMC_MODULE_NAME,
- .owner = THIS_MODULE,
- .pm = &fimc_pm_ops,
+ .of_match_table = fimc_of_match,
+ .name = FIMC_MODULE_NAME,
+ .owner = THIS_MODULE,
+ .pm = &fimc_pm_ops,
}
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 01/10] s5p-csis: Add device tree support
From: Sylwester Nawrocki @ 2013-02-01 19:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359745771-23684-1-git-send-email-s.nawrocki@samsung.com>
s5p-csis is platform device driver for MIPI-CSI frontend to the FIMC
device. This patch support for binding the driver to the MIPI-CSIS
devices instantiated from device tree and for parsing all SoC and
board specific properties.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Changes since v3:
- dropped 'bus-width' property, hard coded the number of supported
data lanes per device also in dt case, it can be derived from the
compatible property if required;
- "samsung,s5pv210-csis" renamed to "samsung,exynos3110-csis",
updated the bindings description.
---
.../bindings/media/soc/samsung-mipi-csis.txt | 82 +++++++++++
drivers/media/platform/s5p-fimc/mipi-csis.c | 154 +++++++++++++++-----
drivers/media/platform/s5p-fimc/mipi-csis.h | 1 +
3 files changed, 202 insertions(+), 35 deletions(-)
create mode 100644 Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt
diff --git a/Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt b/Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt
new file mode 100644
index 0000000..c142272
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt
@@ -0,0 +1,82 @@
+Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver (MIPI CSIS)
+-----------------------------------------------------
+
+Required properties:
+
+- compatible : "samsung,exynos3110-csis" for Exynos3110 (S5PC110, S5PV210)
+ SoCs;
+ "samsung,exynos4210-csis" for Exynos4210 (S5PC210, S5PV310)
+ and later SoCs;
+- reg : physical base address and size of the device memory mapped
+ registers;
+- interrupts : should contain MIPI CSIS interrupt; the format of the
+ interrupt specifier depends on the interrupt controller;
+- vddio-supply : MIPI CSIS I/O and PLL voltage supply (e.g. 1.8V);
+- vddcore-supply : MIPI CSIS Core voltage supply (e.g. 1.1V).
+
+Optional properties:
+
+- clock-frequency : The IP's main (system bus) clock frequency in Hz, default
+ value when this property is not specified is 166 MHz;
+- samsung,csis-wclk : CSI-2 wrapper clock selection. If this property is present
+ external clock from CMU will be used, if not bus clock will
+ be selected.
+
+The device node should contain one 'port' child node with one child 'endpoint'
+node, as outlined in the common media bindings specification. See
+Documentation/devicetree/bindings/media/video-interfaces.txt for details.
+The following are properties specific to these nodes.
+
+port node
+---------
+
+- reg : (required) must be 3 for camera C input (CSIS0) or 4 for
+ camera D input (CSIS1);
+
+endpoint node
+-------------
+
+- data-lanes : (required) an array specifying active physical MIPI-CSI2
+ data input lanes and their mapping to logical lanes; the
+ array's content is unused, only its length is meaningful;
+
+- samsung,csis-hs-settle : (optional) differential receiver (HS-RX) settle time;
+
+
+Example:
+
+ reg0: regulator at 0 {
+ };
+
+ reg1: regulator at 1 {
+ };
+
+/* SoC properties */
+
+ aliases {
+ csis0 = &csis_0;
+ };
+
+ csis_0: csis at 11880000 {
+ compatible = "samsung,exynos4210-csis";
+ reg = <0x11880000 0x1000>;
+ interrupts = <0 78 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+/* Board properties */
+
+ csis_0: csis at 11880000 {
+ clock-frequency = <166000000>;
+ vddio-supply = <®0>;
+ vddcore-supply = <®1>;
+ port {
+ reg = <3>; /* 3 - CSIS0, 4 - CSIS1 */
+ csis0_ep: endpoint {
+ remote-endpoint = <...>;
+ data-lanes = <1>, <2>;
+ samsung,csis-hs-settle = <12>;
+ };
+ };
+ };
diff --git a/drivers/media/platform/s5p-fimc/mipi-csis.c b/drivers/media/platform/s5p-fimc/mipi-csis.c
index 0f5104c..b906bfe 100644
--- a/drivers/media/platform/s5p-fimc/mipi-csis.c
+++ b/drivers/media/platform/s5p-fimc/mipi-csis.c
@@ -19,12 +19,14 @@
#include <linux/kernel.h>
#include <linux/memory.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/videodev2.h>
+#include <media/v4l2-of.h>
#include <media/v4l2-subdev.h>
#include <linux/platform_data/mipi-csis.h>
#include "mipi-csis.h"
@@ -113,6 +115,7 @@ static char *csi_clock_name[] = {
[CSIS_CLK_GATE] = "csis",
};
#define NUM_CSIS_CLOCKS ARRAY_SIZE(csi_clock_name)
+#define DEFAULT_SCLK_CSIS_FREQ 166000000UL
static const char * const csis_supply_name[] = {
"vddcore", /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */
@@ -167,6 +170,11 @@ struct csis_pktbuf {
* @clock: CSIS clocks
* @irq: requested s5p-mipi-csis irq number
* @flags: the state variable for power and streaming control
+ * @clock_frequency: device bus clock frequency
+ * @hs_settle: HS-RX settle time
+ * @num_lanes: number of MIPI-CSI data lanes used
+ * @max_num_lanes: maximum number of MIPI-CSI data lanes supported
+ * @wclk_ext: CSI wrapper clock: 0 - bus clock, 1 - external SCLK_CAM
* @csis_fmt: current CSIS pixel format
* @format: common media bus format for the source and sink pad
* @slock: spinlock protecting structure members below
@@ -184,6 +192,13 @@ struct csis_state {
struct clk *clock[NUM_CSIS_CLOCKS];
int irq;
u32 flags;
+
+ u32 clk_frequency;
+ u32 hs_settle;
+ u32 num_lanes;
+ u32 max_num_lanes;
+ u8 wclk_ext;
+
const struct csis_pix_format *csis_fmt;
struct v4l2_mbus_framefmt format;
@@ -273,7 +288,6 @@ static void s5pcsis_reset(struct csis_state *state)
static void s5pcsis_system_enable(struct csis_state *state, int on)
{
- struct s5p_platform_mipi_csis *pdata = state->pdev->dev.platform_data;
u32 val, mask;
val = s5pcsis_read(state, S5PCSIS_CTRL);
@@ -286,7 +300,7 @@ static void s5pcsis_system_enable(struct csis_state *state, int on)
val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
val &= ~S5PCSIS_DPHYCTRL_ENABLE;
if (on) {
- mask = (1 << (pdata->lanes + 1)) - 1;
+ mask = (1 << (state->num_lanes + 1)) - 1;
val |= (mask & S5PCSIS_DPHYCTRL_ENABLE);
}
s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
@@ -321,15 +335,14 @@ static void s5pcsis_set_hsync_settle(struct csis_state *state, int settle)
static void s5pcsis_set_params(struct csis_state *state)
{
- struct s5p_platform_mipi_csis *pdata = state->pdev->dev.platform_data;
u32 val;
val = s5pcsis_read(state, S5PCSIS_CONFIG);
- val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (pdata->lanes - 1);
+ val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (state->num_lanes - 1);
s5pcsis_write(state, S5PCSIS_CONFIG, val);
__s5pcsis_set_format(state);
- s5pcsis_set_hsync_settle(state, pdata->hs_settle);
+ s5pcsis_set_hsync_settle(state, state->hs_settle);
val = s5pcsis_read(state, S5PCSIS_CTRL);
if (state->csis_fmt->data_alignment == 32)
@@ -338,7 +351,7 @@ static void s5pcsis_set_params(struct csis_state *state)
val &= ~S5PCSIS_CTRL_ALIGN_32BIT;
val &= ~S5PCSIS_CTRL_WCLK_EXTCLK;
- if (pdata->wclk_source)
+ if (state->wclk_ext)
val |= S5PCSIS_CTRL_WCLK_EXTCLK;
s5pcsis_write(state, S5PCSIS_CTRL, val);
@@ -701,54 +714,114 @@ static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static int s5pcsis_get_platform_data(struct platform_device *pdev,
+ struct csis_state *state)
+{
+ struct s5p_platform_mipi_csis *pdata = pdev->dev.platform_data;
+
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "Platform data not specified\n");
+ return -EINVAL;
+ }
+
+ state->clk_frequency = pdata->clk_rate;
+ state->num_lanes = pdata->lanes;
+ state->hs_settle = pdata->hs_settle;
+ state->index = max(0, pdev->id);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static int s5pcsis_parse_dt(struct platform_device *pdev,
+ struct csis_state *state)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct v4l2_of_endpoint endpoint;
+ int ret;
+
+ state->index = of_alias_get_id(node, "csis");
+ if (state->index < 0 || state->index >= CSIS_MAX_ENTITIES)
+ return -EINVAL;
+
+ if (of_property_read_u32(node, "clock-frequency",
+ &state->clk_frequency))
+ state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
+ /*
+ * Get endpoint node. We care only about first child
+ * nodes since these are the only ones available.
+ */
+ while ((node = of_get_next_child(node, NULL))) {
+ if (!of_node_cmp(node->name, "endpoint"))
+ break;
+ of_node_put(node);
+ };
+ if (!node)
+ return -EINVAL;
+ of_property_read_u32(node, "samsung,csis-hs-settle",
+ &state->hs_settle);
+ state->wclk_ext = of_property_read_bool(node,
+ "samsung,csis-wclk");
+ ret = v4l2_of_parse_mipi_csi2(node, &endpoint);
+ state->num_lanes = endpoint.mbus.mipi_csi2.num_data_lanes;
+
+ of_node_put(node);
+ return 0;
+}
+#else
+#define s5pcsis_parse_dt(pdev, state) (-ENOSYS)
+#endif
+
static int s5pcsis_probe(struct platform_device *pdev)
{
- struct s5p_platform_mipi_csis *pdata;
+ struct device *dev = &pdev->dev;
struct resource *mem_res;
struct csis_state *state;
int ret = -ENOMEM;
int i;
- state = devm_kzalloc(&pdev->dev, sizeof(*state), GFP_KERNEL);
+ state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
if (!state)
return -ENOMEM;
mutex_init(&state->lock);
spin_lock_init(&state->slock);
-
state->pdev = pdev;
- state->index = max(0, pdev->id);
- pdata = pdev->dev.platform_data;
- if (pdata == NULL) {
- dev_err(&pdev->dev, "Platform data not fully specified\n");
- return -EINVAL;
- }
+ if (dev->of_node)
+ ret = s5pcsis_parse_dt(pdev, state);
+ else
+ ret = s5pcsis_get_platform_data(pdev, state);
+ if (ret < 0)
+ return ret;
+ if (state->index == 1)
+ state->max_num_lanes = CSIS1_MAX_LANES;
+ else
+ state->max_num_lanes = CSIS0_MAX_LANES;
- if ((state->index == 1 && pdata->lanes > CSIS1_MAX_LANES) ||
- pdata->lanes > CSIS0_MAX_LANES) {
- dev_err(&pdev->dev, "Unsupported number of data lanes: %d\n",
- pdata->lanes);
+ if (state->num_lanes == 0 || state->num_lanes > state->max_num_lanes) {
+ dev_err(dev, "Unsupported number of data lanes: %d (max. %d)\n",
+ state->num_lanes, state->max_num_lanes);
return -EINVAL;
}
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- state->regs = devm_request_and_ioremap(&pdev->dev, mem_res);
+ state->regs = devm_request_and_ioremap(dev, mem_res);
if (state->regs == NULL) {
- dev_err(&pdev->dev, "Failed to request and remap io memory\n");
+ dev_err(dev, "Failed to request and remap io memory\n");
return -ENXIO;
}
state->irq = platform_get_irq(pdev, 0);
if (state->irq < 0) {
- dev_err(&pdev->dev, "Failed to get irq\n");
+ dev_err(dev, "Failed to get irq\n");
return state->irq;
}
for (i = 0; i < CSIS_NUM_SUPPLIES; i++)
state->supplies[i].supply = csis_supply_name[i];
- ret = devm_regulator_bulk_get(&pdev->dev, CSIS_NUM_SUPPLIES,
+ ret = devm_regulator_bulk_get(dev, CSIS_NUM_SUPPLIES,
state->supplies);
if (ret)
return ret;
@@ -757,11 +830,11 @@ static int s5pcsis_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- if (pdata->clk_rate)
+ if (state->clk_frequency)
ret = clk_set_rate(state->clock[CSIS_CLK_MUX],
- pdata->clk_rate);
+ state->clk_frequency);
else
- dev_WARN(&pdev->dev, "No clock frequency specified!\n");
+ dev_WARN(dev, "No clock frequency specified!\n");
if (ret < 0)
goto e_clkput;
@@ -769,16 +842,17 @@ static int s5pcsis_probe(struct platform_device *pdev)
if (ret < 0)
goto e_clkput;
- ret = devm_request_irq(&pdev->dev, state->irq, s5pcsis_irq_handler,
- 0, dev_name(&pdev->dev), state);
+ ret = devm_request_irq(dev, state->irq, s5pcsis_irq_handler,
+ 0, dev_name(dev), state);
if (ret) {
- dev_err(&pdev->dev, "Interrupt request failed\n");
+ dev_err(dev, "Interrupt request failed\n");
goto e_clkdis;
}
v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops);
state->sd.owner = THIS_MODULE;
- strlcpy(state->sd.name, dev_name(&pdev->dev), sizeof(state->sd.name));
+ snprintf(state->sd.name, sizeof(state->sd.name), "%s.%d",
+ CSIS_SUBDEV_NAME, state->index);
state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
state->csis_fmt = &s5pcsis_formats[0];
@@ -798,10 +872,12 @@ static int s5pcsis_probe(struct platform_device *pdev)
/* .. and a pointer to the subdev. */
platform_set_drvdata(pdev, &state->sd);
-
memcpy(state->events, s5pcsis_events, sizeof(state->events));
+ pm_runtime_enable(dev);
- pm_runtime_enable(&pdev->dev);
+ dev_info(&pdev->dev, "lanes: %d, hs_settle: %d, wclk: %d, freq: %u\n",
+ state->num_lanes, state->hs_settle, state->wclk_ext,
+ state->clk_frequency);
return 0;
e_clkdis:
@@ -925,13 +1001,21 @@ static const struct dev_pm_ops s5pcsis_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
};
+static const struct of_device_id s5pcsis_of_match[] __devinitconst = {
+ { .compatible = "samsung,exynos3110-csis" },
+ { .compatible = "samsung,exynos4210-csis" },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, s5pcsis_of_match);
+
static struct platform_driver s5pcsis_driver = {
.probe = s5pcsis_probe,
.remove = s5pcsis_remove,
.driver = {
- .name = CSIS_DRIVER_NAME,
- .owner = THIS_MODULE,
- .pm = &s5pcsis_pm_ops,
+ .of_match_table = s5pcsis_of_match,
+ .name = CSIS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = &s5pcsis_pm_ops,
},
};
diff --git a/drivers/media/platform/s5p-fimc/mipi-csis.h b/drivers/media/platform/s5p-fimc/mipi-csis.h
index 2709286..28c11c4 100644
--- a/drivers/media/platform/s5p-fimc/mipi-csis.h
+++ b/drivers/media/platform/s5p-fimc/mipi-csis.h
@@ -11,6 +11,7 @@
#define S5P_MIPI_CSIS_H_
#define CSIS_DRIVER_NAME "s5p-mipi-csis"
+#define CSIS_SUBDEV_NAME CSIS_DRIVER_NAME
#define CSIS_MAX_ENTITIES 2
#define CSIS0_MAX_LANES 4
#define CSIS1_MAX_LANES 2
--
1.7.9.5
^ permalink raw reply related
* [PATCH v4 00/10] Device tree support for Exynos SoC camera subsystem
From: Sylwester Nawrocki @ 2013-02-01 19:09 UTC (permalink / raw)
To: linux-arm-kernel
This is an updated patch series adding initial support for the Exynos4
SoC series camera subsystem. It is based on the video interfaces common
device tree bindings and depends on patch series [1]. The full source
tree can be browsed at [2].
I've dropped the RFC tag from this series and I'm going to continue with
adding support for asynchronous sensor subdevs registration and the
FIMC-IS on top of it. Unless there are further changes in the bindings.
Still, any comments are welcome.
The changes are listed in each patch, if any.
This series likely won't make it to v3.9. It would be nice, but there
seems not to be much interest in getting [1] in the mainline and the
reviews are relatively slow.
Any Ack/nack from the device tree maintainers are welcome, so I could
finally have this patch set merged and carry on with other, even more
interesting things. :)
Thanks,
Sylwester
[1] http://www.spinics.net/lists/linux-media/msg59471.html
[2] http://git.linuxtv.org/snawrocki/samsung.git/exynos_fimc
Sylwester Nawrocki (10):
s5p-csis: Add device tree support
s5p-fimc: Add device tree support for FIMC devices
s5p-fimc: Add device tree support for FIMC-LITE devices
s5p-fimc: Add device tree support for the main media device driver
s5p-fimc: Add device tree based sensors registration
s5p-fimc: Use pinctrl API for camera ports configuration
ARM: dts: Add camera to node exynos4.dtsi
ARM: dts: Add ISP power domain node for Exynos4x12
ARM: dts: Add FIMC and MIPI CSIS device nodes for Exynos4x12
ARM: dts: Correct camera pinctrl nodes for Exynos4x12 SoCs
.../devicetree/bindings/media/soc/samsung-fimc.txt | 183 +++++++++++
.../bindings/media/soc/samsung-mipi-csis.txt | 82 +++++
arch/arm/boot/dts/exynos4.dtsi | 64 ++++
arch/arm/boot/dts/exynos4x12-pinctrl.dtsi | 26 +-
arch/arm/boot/dts/exynos4x12.dtsi | 52 ++++
drivers/media/platform/s5p-fimc/fimc-capture.c | 2 +-
drivers/media/platform/s5p-fimc/fimc-core.c | 94 ++++--
drivers/media/platform/s5p-fimc/fimc-lite.c | 65 ++--
drivers/media/platform/s5p-fimc/fimc-mdevice.c | 319 ++++++++++++++++++--
drivers/media/platform/s5p-fimc/fimc-mdevice.h | 4 +
drivers/media/platform/s5p-fimc/mipi-csis.c | 154 +++++++---
drivers/media/platform/s5p-fimc/mipi-csis.h | 1 +
include/media/s5p_fimc.h | 17 ++
13 files changed, 936 insertions(+), 127 deletions(-)
create mode 100644 Documentation/devicetree/bindings/media/soc/samsung-fimc.txt
create mode 100644 Documentation/devicetree/bindings/media/soc/samsung-mipi-csis.txt
--
1.7.9.5
^ permalink raw reply
* [PATCH v7 01/10] ARM: davinci: move private EDMA API to arm/common
From: Matt Porter @ 2013-02-01 18:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2077c13e12314dc3adc8e5b653855da0@DFLE72.ent.ti.com>
On Fri, Feb 01, 2013 at 07:52:46PM +0000, Sergei Shtylyov wrote:
> Hello.
>
> On 02/01/2013 09:49 PM, Matt Porter wrote:
>
> >>> Move mach-davinci/dma.c to common/edma.c so it can be used
> >>> by OMAP (specifically AM33xx) as well.
>
> >> I think this should rather go to drivers/dma/?
>
> > No, this is the private EDMA API. It's the analogous thing to
> > the private OMAP dma API that is in plat-omap/dma.c. The actual
> > dmaengine driver is in drivers/dma/edma.c as a wrapper around
> > this...same way OMAP DMA engine conversion is being done.
>
> Keeps me wondering why we couldn't have the same with CPPI 4.1 when I proposed
> that, instead of waiting indefinitely for TI to convert it to drivers/dma/
> directly. We could have working MUSB DMA on OMAP-L1x/Sitara all this time... Sigh.
That is a shame. Yeah, I've pointed out that I was doing this exactly
the same way as was acceptable for the OMAP DMA conversion since it was
in RFC. The reasons are sound since in both cases, we have many drivers
to convert that need to continue using the private DMA APIs.
-Matt
>
^ permalink raw reply
* [PATCH v7 01/10] ARM: davinci: move private EDMA API to arm/common
From: Felipe Balbi @ 2013-02-01 18:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <510C1D0E.6030401@mvista.com>
Hi,
On Fri, Feb 01, 2013 at 10:52:46PM +0300, Sergei Shtylyov wrote:
> Hello.
>
> On 02/01/2013 09:49 PM, Matt Porter wrote:
>
> >>> Move mach-davinci/dma.c to common/edma.c so it can be used
> >>> by OMAP (specifically AM33xx) as well.
>
> >> I think this should rather go to drivers/dma/?
>
> > No, this is the private EDMA API. It's the analogous thing to
> > the private OMAP dma API that is in plat-omap/dma.c. The actual
> > dmaengine driver is in drivers/dma/edma.c as a wrapper around
> > this...same way OMAP DMA engine conversion is being done.
>
> Keeps me wondering why we couldn't have the same with CPPI 4.1 when I proposed
> that, instead of waiting indefinitely for TI to convert it to drivers/dma/
> directly. We could have working MUSB DMA on OMAP-L1x/Sitara all this time... Sigh.
good point, do you wanna send some patches ?
I guess to make the MUSB side simpler we would need musb-dma-engine glue
to map dmaengine to the private MUSB API. Then we would have some
starting point to also move inventra (and anybody else) to dmaengine
API.
Once that's done, we drop MUSB's private API.
--
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130201/82d77776/attachment.sig>
^ permalink raw reply
* [PATCH v7 01/10] ARM: davinci: move private EDMA API to arm/common
From: Matt Porter @ 2013-02-01 18:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5022f635a527470dbd0be932063e9cd2@DFLE72.ent.ti.com>
On Fri, Feb 01, 2013 at 06:41:08PM +0000, Tony Lindgren wrote:
> * Matt Porter <mporter@ti.com> [130201 10:25]:
> > Move mach-davinci/dma.c to common/edma.c so it can be used
> > by OMAP (specifically AM33xx) as well.
>
> I think this should rather go to drivers/dma/?
No, this is the private EDMA API. It's the analogous thing to
the private OMAP dma API that is in plat-omap/dma.c. The actual
dmaengine driver is in drivers/dma/edma.c as a wrapper around
this...same way OMAP DMA engine conversion is being done.
-Matt
^ permalink raw reply
* [PATCH] RX-51: Add leds lp5523 names from Maemo 5 2.6.28 kernel
From: Tony Lindgren @ 2013-02-01 18:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358650244-29722-1-git-send-email-pali.rohar@gmail.com>
* Pali Roh?r <pali.rohar@gmail.com> [130119 18:54]:
> Signed-off-by: Pali Roh?r <pali.rohar@gmail.com>
> ---
> arch/arm/mach-omap2/board-rx51-peripherals.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
Thanks applying into omap-for-v3.9/board with the subject
also pasted to the description.
Tony
> diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
> index 7611958..9a0dbb7 100644
> --- a/arch/arm/mach-omap2/board-rx51-peripherals.c
> +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
> @@ -168,30 +168,39 @@ static struct tsl2563_platform_data rx51_tsl2563_platform_data = {
> #if defined(CONFIG_LEDS_LP5523) || defined(CONFIG_LEDS_LP5523_MODULE)
> static struct lp5523_led_config rx51_lp5523_led_config[] = {
> {
> + .name = "lp5523:kb1",
> .chan_nr = 0,
> .led_current = 50,
> }, {
> + .name = "lp5523:kb2",
> .chan_nr = 1,
> .led_current = 50,
> }, {
> + .name = "lp5523:kb3",
> .chan_nr = 2,
> .led_current = 50,
> }, {
> + .name = "lp5523:kb4",
> .chan_nr = 3,
> .led_current = 50,
> }, {
> + .name = "lp5523:b",
> .chan_nr = 4,
> .led_current = 50,
> }, {
> + .name = "lp5523:g",
> .chan_nr = 5,
> .led_current = 50,
> }, {
> + .name = "lp5523:r",
> .chan_nr = 6,
> .led_current = 50,
> }, {
> + .name = "lp5523:kb5",
> .chan_nr = 7,
> .led_current = 50,
> }, {
> + .name = "lp5523:kb6",
> .chan_nr = 8,
> .led_current = 50,
> }
> --
> 1.7.10.4
>
^ permalink raw reply
* [PATCH v4] ARM: OMAP2+: AM33XX: omap2plus_defconfig: Add support for few drivers
From: Tony Lindgren @ 2013-02-01 18:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <331ABD5ECB02734CA317220B2BBEABC13EAF03E7@DBDE01.ent.ti.com>
* AnilKumar, Chimata <anilkumar@ti.com> [130118 03:23]:
> On Thu, Jan 03, 2013 at 14:07:59, AnilKumar, Chimata wrote:
> > Adds tps65910 PMIC, lis3lv02d accelerometer, tsl2550 ambient light sensor,
> > tmp275 temperature sensor, matrix keypad, gbio based leds and D_CAN drivers
> > support. These peripherals are present on AM33XX family of devices (EVM,
> > BeagleBone and EVMSK). One has to manually enable these support to use the
> > drivers, so this patch enables all the drivers in omap2plus_defconfig
>
> Hi Tony,
>
> Could you please pull this patch, if there are no further comments?
Thanks applying into omap-for-v3.9/board.
Regards,
Tony
^ permalink raw reply
* [PATCH v7 01/10] ARM: davinci: move private EDMA API to arm/common
From: Tony Lindgren @ 2013-02-01 18:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359742975-10421-2-git-send-email-mporter@ti.com>
* Matt Porter <mporter@ti.com> [130201 10:25]:
> Move mach-davinci/dma.c to common/edma.c so it can be used
> by OMAP (specifically AM33xx) as well.
I think this should rather go to drivers/dma/?
Tony
^ permalink raw reply
* [PATCH v4] ARM: LPAE: Fix mapping in alloc_init_pte for unaligned addresses
From: Christoffer Dall @ 2013-02-01 18:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130201174246.GJ5151@arm.com>
[...]
>
> Another try. This time I kept the same logic as before but added a loop
> on the outside (and indented the code). With classic MMU
> pmd_addr_end(addr, end) always return end, so the logic doesn't change.
> With LPAE we should get the standard looping over pmd entries. Again,
> only tested on C-A9.
>
I think the logic should be explained in a comment in the code if we
take this approach - it's not logical to understand that you switch
between using the outer vs. inner loop depending on your config.
>
> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> index 9f06102..47154f3 100644
> --- a/arch/arm/mm/mmu.c
> +++ b/arch/arm/mm/mmu.c
> @@ -581,34 +581,36 @@ static void __init alloc_init_section(pud_t *pud, unsigned long addr,
> const struct mem_type *type)
> {
> pmd_t *pmd = pmd_offset(pud, addr);
> + unsigned long next;
>
> - /*
> - * Try a section mapping - end, addr and phys must all be aligned
> - * to a section boundary. Note that PMDs refer to the individual
> - * L1 entries, whereas PGDs refer to a group of L1 entries making
> - * up one logical pointer to an L2 table.
> - */
> - if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
> - pmd_t *p = pmd;
> + do {
> + next = pmd_addr_end(addr, end);
> +
> + /*
> + * Try a section mapping - next, addr and phys must all be
> + * aligned to a section boundary. Note that PMDs refer to the
> + * individual L1 entries, whereas PGDs refer to a group of L1
> + * entries making up one logical pointer to an L2 table.
> + */
> + if (((addr | next | phys) & ~SECTION_MASK) == 0) {
> + pmd_t *p = pmd;
>
> #ifndef CONFIG_ARM_LPAE
> - if (addr & SECTION_SIZE)
> - pmd++;
> + if (addr & SECTION_SIZE)
> + pmd++;
> #endif
perhaps we could comment this ifdef now when we're at it, I spent a
considerable amount of time understanding it, and now I forgot again.
IIRC the logic relies on state set up during early assembly boot,
which is a little much to ask of the reader of this code...
> + do {
> + *pmd = __pmd(phys | type->prot_sect);
> + phys += SECTION_SIZE;
> + } while (pmd++, addr += SECTION_SIZE, addr != next);
>
> - do {
> - *pmd = __pmd(phys | type->prot_sect);
> - phys += SECTION_SIZE;
> - } while (pmd++, addr += SECTION_SIZE, addr != end);
> -
> - flush_pmd_entry(p);
> - } else {
> - /*
> - * No need to loop; pte's aren't interested in the
> - * individual L1 entries.
> - */
> - alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
> - }
> + flush_pmd_entry(p);
> + } else {
> + alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys), type);
> + phys += next - addr;
> + pmd++;
> + }
> + } while (addr = next, addr != end);
aren't you still wasting memory for the individual PTEs inside alloc_init_pte?
also, I would prefer having two distinct loops than this outer/inner
scheme, but with the right comment I'm fine with it.
> }
>
> static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
Let me know if you'd like me to test it on omap5.
-Christoffer
^ permalink raw reply
* [PATCH] ARM: OMAP1: nokia770: enable CBUS/Retu
From: Tony Lindgren @ 2013-02-01 18:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1355953262-4352-1-git-send-email-aaro.koskinen@iki.fi>
* Aaro Koskinen <aaro.koskinen@iki.fi> [121219 13:44]:
> Add needed platform data so that it's possible to use Retu and e.g. feed
> Retu watchdog.
Thanks applying into omap-for-v3.9/board.
Regards,
Tony
^ permalink raw reply
* [PATCH 1/2] ARM: OMAP2+: omap2plus_defconfig: enable TFP410 chip support
From: Tony Lindgren @ 2013-02-01 18:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CABxcv=nyuOJaLcHR=DgnXSxLkF-TqU2_mxt=46qZVWg_Vhh_9Q@mail.gmail.com>
* Javier Martinez Canillas <javier@dowhile0.org> [130110 01:31]:
> On Wed, Dec 19, 2012 at 4:26 PM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> > On 2012-12-19 14:33, Javier Martinez Canillas wrote:
> >> Many OMAP3 based boards such as Beagle, Overo and IGEP use
> >> the TFP410 DPI-to-DVI chip. So, it's good to have it built
> >> as a module by default on OMAP2+ config.
> >
> > Also on OMAP4 boards, like Panda.
> >
> >> Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
> >> ---
> >> arch/arm/configs/omap2plus_defconfig | 1 +
> >> 1 files changed, 1 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
> >> index a1dc5c0..da530a0 100644
> >> --- a/arch/arm/configs/omap2plus_defconfig
> >> +++ b/arch/arm/configs/omap2plus_defconfig
> >> @@ -146,6 +146,7 @@ CONFIG_OMAP2_DSS_SDI=y
> >> CONFIG_OMAP2_DSS_DSI=y
> >> CONFIG_FB_OMAP2=m
> >> CONFIG_PANEL_GENERIC_DPI=m
> >> +CONFIG_PANEL_TFP410=m
> >> CONFIG_PANEL_SHARP_LS037V7DW01=m
> >> CONFIG_PANEL_NEC_NL8048HL11_01B=m
> >> CONFIG_PANEL_TAAL=m
> >>
> >
> > For both patches:
> >
> > Acked-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
> >
> > Tomi
> >
>
> Hello Tony,
>
> Any comments on these?
No comments, applying into omap-for-v3.9/board thanks.
Tony
^ permalink raw reply
* [PATCH v7 00/10] DMA Engine support for AM33XX
From: Matt Porter @ 2013-02-01 18:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359742975-10421-1-git-send-email-mporter@ti.com>
On Fri, Feb 01, 2013 at 01:22:45PM -0500, Matt Porter wrote:
<snip>
> This series adds DMA Engine support for AM33xx, which uses
> an EDMA DMAC. The EDMA DMAC has been previously supported by only
> a private API implementation (much like the situation with OMAP
> DMA) found on the DaVinci family of SoCs.
Tony,
Will you be able to take this series in through your tree? It appears we
just need acks on the new bindings and the compat api change. I haven't
heard from you or Benoit on the dts patches so it seems those are ready
as well.
Thanks,
Matt
>
> The series applies on top of 3.8-rc5 and the following patches:
>
> - dmaengine DT support and edma dmaengine driver fix from
> the git://git.infradead.org/users/vkoul/slave-dma.git next
> branch
>
> The approach taken is similar to how OMAP DMA is being converted to
> DMA Engine support. With the functional EDMA private API already
> existing in mach-davinci/dma.c, we first move that to an ARM common
> area so it can be shared. Adding DT and runtime PM support to the
> private EDMA API implementation allows it to run on AM33xx. AM33xx
> *only* boots using DT so we leverage Jon's generic DT DMA helpers to
> register EDMA DMAC with the of_dma framework and then add support
> for calling the dma_request_slave_channel() API to both the mmc
> and spi drivers.
>
> With this series both BeagleBone and the AM335x EVM have working
> SPI DMA support (and MMC support with the separate MMC series).
>
> This is tested on BeagleBone with a SPI framebuffer driver and MMC
> rootfs. A trivial gpio DMA event misc driver was used to test the
> crossbar DMA event support. It is also tested on the AM335x EVM
> with the onboard SPI flash and MMC rootfs. The branch at
> https://github.com/ohporter/linux/tree/edma-dmaengine-am33xx-v7
> has the complete series, dependencies, and some test
> drivers/defconfigs. Note that MMC can only be tested with a
> separate MMC dmaengine/DT series applied.
>
> Regression testing was done on AM180x-EVM (which also makes use
> of the EDMA dmaengine driver and the EDMA private API) using SD,
> SPI flash, and the onboard audio supported by the ASoC Davinci
> driver. Regression testing was also done on a BeagleBoard xM
> booting from the legacy board file using MMC rootfs.
>
>
> Matt Porter (10):
> ARM: davinci: move private EDMA API to arm/common
> ARM: edma: remove unused transfer controller handlers
> ARM: edma: add AM33XX support to the private EDMA API
> dmaengine: edma: enable build for AM33XX
> dmaengine: edma: Add TI EDMA device tree binding
> ARM: dts: add AM33XX EDMA support
> dmaengine: add dma_request_slave_channel_compat()
> spi: omap2-mcspi: convert to dma_request_slave_channel_compat()
> spi: omap2-mcspi: add generic DMA request support to the DT binding
> ARM: dts: add AM33XX SPI DMA support
>
> Documentation/devicetree/bindings/dma/ti-edma.txt | 49 +++
> Documentation/devicetree/bindings/spi/omap-spi.txt | 27 +-
> arch/arm/Kconfig | 1 +
> arch/arm/boot/dts/am33xx.dtsi | 30 ++
> arch/arm/common/Kconfig | 3 +
> arch/arm/common/Makefile | 1 +
> arch/arm/{mach-davinci/dma.c => common/edma.c} | 342 +++++++++++++++++---
> arch/arm/mach-davinci/Makefile | 2 +-
> arch/arm/mach-davinci/board-tnetv107x-evm.c | 2 +-
> arch/arm/mach-davinci/davinci.h | 2 +-
> arch/arm/mach-davinci/devices-tnetv107x.c | 2 +-
> arch/arm/mach-davinci/devices.c | 6 +-
> arch/arm/mach-davinci/dm355.c | 2 +-
> arch/arm/mach-davinci/dm365.c | 2 +-
> arch/arm/mach-davinci/dm644x.c | 2 +-
> arch/arm/mach-davinci/dm646x.c | 2 +-
> arch/arm/mach-davinci/include/mach/da8xx.h | 2 +-
> arch/arm/plat-omap/Kconfig | 1 +
> drivers/dma/Kconfig | 2 +-
> drivers/dma/edma.c | 2 +-
> drivers/mmc/host/davinci_mmc.c | 1 +
> drivers/spi/spi-omap2-mcspi.c | 65 ++--
> include/linux/dmaengine.h | 16 +
> include/linux/mfd/davinci_voicecodec.h | 3 +-
> .../mach => include/linux/platform_data}/edma.h | 90 +-----
> include/linux/platform_data/spi-davinci.h | 2 +-
> sound/soc/davinci/davinci-evm.c | 1 +
> sound/soc/davinci/davinci-pcm.c | 1 +
> sound/soc/davinci/davinci-pcm.h | 2 +-
> sound/soc/davinci/davinci-sffsdr.c | 7 +-
> 30 files changed, 496 insertions(+), 174 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/dma/ti-edma.txt
> rename arch/arm/{mach-davinci/dma.c => common/edma.c} (86%)
> rename {arch/arm/mach-davinci/include/mach => include/linux/platform_data}/edma.h (59%)
>
> --
> 1.7.9.5
>
^ permalink raw reply
* [PATCH v7 07/10] dmaengine: add dma_request_slave_channel_compat()
From: Matt Porter @ 2013-02-01 18:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359742975-10421-8-git-send-email-mporter@ti.com>
On Fri, Feb 01, 2013 at 01:22:52PM -0500, Matt Porter wrote:
> Adds a dma_request_slave_channel_compat() wrapper which accepts
> both the arguments from dma_request_channel() and
> dma_request_slave_channel(). Based on whether the driver is
> instantiated via DT, the appropriate channel request call will be
> made.
>
> This allows for a much cleaner migration of drivers to the
> dmaengine DT API as platforms continue to be mixed between those
> that boot using DT and those that do not.
>
> Suggested-by: Tony Lindgren <tony@atomide.com>
> Signed-off-by: Matt Porter <mporter@ti.com>
> Acked-by: Tony Lindgren <tony@atomide.com>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
Vinod, can I get an ack on this one?
-Matt
> ---
> include/linux/dmaengine.h | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> index bfcdecb..17d8ffd 100644
> --- a/include/linux/dmaengine.h
> +++ b/include/linux/dmaengine.h
> @@ -1001,6 +1001,22 @@ void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
> struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type);
> struct dma_chan *net_dma_find_channel(void);
> #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
> +#define dma_request_slave_channel_compat(mask, x, y, dev, name) \
> + __dma_request_slave_channel_compat(&(mask), x, y, dev, name)
> +
> +static inline struct dma_chan
> +*__dma_request_slave_channel_compat(dma_cap_mask_t *mask, dma_filter_fn fn,
> + void *fn_param, struct device *dev,
> + char *name)
> +{
> + struct dma_chan *chan;
> +
> + chan = dma_request_slave_channel(dev, name);
> + if (chan)
> + return chan;
> +
> + return __dma_request_channel(mask, fn, fn_param);
> +}
>
> /* --- Helper iov-locking functions --- */
>
> --
> 1.7.9.5
>
^ permalink raw reply
* [PATCH v7 05/10] dmaengine: edma: Add TI EDMA device tree binding
From: Matt Porter @ 2013-02-01 18:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359742975-10421-6-git-send-email-mporter@ti.com>
On Fri, Feb 01, 2013 at 01:22:50PM -0500, Matt Porter wrote:
> The binding definition is based on the generic DMA controller
> binding.
>
> Signed-off-by: Matt Porter <mporter@ti.com>
Grant or Rob, can I get an ack on this binding and others in this
series?
> ---
> Documentation/devicetree/bindings/dma/ti-edma.txt | 49 +++++++++++++++++++++
> 1 file changed, 49 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/dma/ti-edma.txt
>
> diff --git a/Documentation/devicetree/bindings/dma/ti-edma.txt b/Documentation/devicetree/bindings/dma/ti-edma.txt
> new file mode 100644
> index 0000000..075a60e3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dma/ti-edma.txt
> @@ -0,0 +1,49 @@
> +TI EDMA
> +
> +Required properties:
> +- compatible : "ti,edma3"
> +- ti,hwmods: Name of the hwmods associated to the EDMA
> +- ti,edma-regions: Number of regions
> +- ti,edma-slots: Number of slots
> +- ti,edma-queue-tc-map: List of transfer control to queue mappings
> +- ti,edma-queue-priority-map: List of queue priority mappings
> +- ti,edma-default-queue: Default queue value
> +
> +Optional properties:
> +- ti,edma-reserved-channels: List of reserved channel regions
> +- ti,edma-reserved-slots: List of reserved slot regions
> +- ti,edma-xbar-event-map: Crossbar event to channel map
> +
> +Example:
> +
> +edma: edma at 49000000 {
> + reg = <0x49000000 0x10000>;
> + interrupt-parent = <&intc>;
> + interrupts = <12 13 14>;
> + compatible = "ti,edma3";
> + ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2";
> + #dma-cells = <1>;
> + dma-channels = <64>;
> + ti,edma-regions = <4>;
> + ti,edma-slots = <256>;
> + ti,edma-reserved-channels = <0 2
> + 14 2
> + 26 6
> + 48 4
> + 56 8>;
> + ti,edma-reserved-slots = <0 2
> + 14 2
> + 26 6
> + 48 4
> + 56 8
> + 64 127>;
> + ti,edma-queue-tc-map = <0 0
> + 1 1
> + 2 2>;
> + ti,edma-queue-priority-map = <0 0
> + 1 1
> + 2 2>;
> + ti,edma-default-queue = <0>;
> + ti,edma-xbar-event-map = <1 12
> + 2 13>;
> +};
> --
> 1.7.9.5
>
^ permalink raw reply
* [PATCH 1/1] ARM: OMAP3: igep0020: simplify GPIO LEDs dependencies
From: Tony Lindgren @ 2013-02-01 18:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CABxcv=k6wypYO+JOV1rWyuGtR-seNQ2PFqym7QsAdkC+mC7P8g@mail.gmail.com>
* Javier Martinez Canillas <javier@dowhile0.org> [121220 06:08]:
>
> Any comments on this patch?
No comments, sorry for the delay. Applying it into omap-for-v3.9/board.
> I wonder if I should keep sending fixes/improvements for board-igep0020.c
>
> I already sent an initial Device Tree support for IGEP boards [1] and
> Benoit told me he is going to queue for 3.9. But still doesn't support
> many peripherals found on these boards because they still don't proper
> DT support, for instance NAND and Ethernet need the GPMC bindings
> patches that haven't hit mainline yet.
>
> So, it seems I will have to keep working on the board file until it
> can be completely deprecated.
Yes we still have few missing things for complete DT support. While we
are working at it, let's just keep the board-*.c changes to minimum.
Regards,
Tony
> Thanks a lot and best regards,
> Javier
>
> [1]: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg82383.html
^ permalink raw reply
* [PATCH v7 10/10] ARM: dts: add AM33XX SPI DMA support
From: Matt Porter @ 2013-02-01 18:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359742975-10421-1-git-send-email-mporter@ti.com>
Adds DMA resources to the AM33XX SPI nodes.
Signed-off-by: Matt Porter <mporter@ti.com>
---
arch/arm/boot/dts/am33xx.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index e711ffb..ddf702a 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -328,6 +328,11 @@
interrupt = <65>;
ti,spi-num-cs = <2>;
ti,hwmods = "spi0";
+ dmas = <&edma 16
+ &edma 17
+ &edma 18
+ &edma 19>;
+ dma-names = "tx0", "rx0", "tx1", "rx1";
status = "disabled";
};
@@ -339,6 +344,11 @@
interrupt = <125>;
ti,spi-num-cs = <2>;
ti,hwmods = "spi1";
+ dmas = <&edma 42
+ &edma 43
+ &edma 44
+ &edma 45>;
+ dma-names = "tx0", "rx0", "tx1", "rx1";
status = "disabled";
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v7 09/10] spi: omap2-mcspi: add generic DMA request support to the DT binding
From: Matt Porter @ 2013-02-01 18:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359742975-10421-1-git-send-email-mporter@ti.com>
The binding definition is based on the generic DMA request binding
Signed-off-by: Matt Porter <mporter@ti.com>
---
Documentation/devicetree/bindings/spi/omap-spi.txt | 27 +++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/spi/omap-spi.txt b/Documentation/devicetree/bindings/spi/omap-spi.txt
index 938809c..4c85c4c 100644
--- a/Documentation/devicetree/bindings/spi/omap-spi.txt
+++ b/Documentation/devicetree/bindings/spi/omap-spi.txt
@@ -10,7 +10,18 @@ Required properties:
input. The default is D0 as input and
D1 as output.
-Example:
+Optional properties:
+- dmas: List of DMA specifiers with the controller specific format
+ as described in the generic DMA client binding. A tx and rx
+ specifier is required for each chip select.
+- dma-names: List of DMA request names. These strings correspond
+ 1:1 with the DMA specifiers listed in dmas. The string naming
+ is to be "rxN" and "txN" for RX and TX requests,
+ respectively, where N equals the chip select number.
+
+Examples:
+
+[hwmod populated DMA resources]
mcspi1: mcspi at 1 {
#address-cells = <1>;
@@ -20,3 +31,17 @@ mcspi1: mcspi at 1 {
ti,spi-num-cs = <4>;
};
+[generic DMA request binding]
+
+mcspi1: mcspi at 1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "ti,omap4-mcspi";
+ ti,hwmods = "mcspi1";
+ ti,spi-num-cs = <2>;
+ dmas = <&edma 42
+ &edma 43
+ &edma 44
+ &edma 45>;
+ dma-names = "tx0", "rx0", "tx1", "rx1";
+};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v7 08/10] spi: omap2-mcspi: convert to dma_request_slave_channel_compat()
From: Matt Porter @ 2013-02-01 18:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359742975-10421-1-git-send-email-mporter@ti.com>
Convert dmaengine channel requests to use
dma_request_slave_channel_compat(). This supports the DT case of
platforms requiring channel selection from either the OMAP DMA or
the EDMA engine. AM33xx only boots from DT and is the only user
implementing EDMA so in the !DT case we can default to the OMAP DMA
filter.
Signed-off-by: Matt Porter <mporter@ti.com>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
drivers/spi/spi-omap2-mcspi.c | 65 ++++++++++++++++++++++++++++-------------
1 file changed, 45 insertions(+), 20 deletions(-)
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index b610f52..2c02c02 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -102,6 +102,9 @@ struct omap2_mcspi_dma {
struct completion dma_tx_completion;
struct completion dma_rx_completion;
+
+ char dma_rx_ch_name[14];
+ char dma_tx_ch_name[14];
};
/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
@@ -822,14 +825,23 @@ static int omap2_mcspi_request_dma(struct spi_device *spi)
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
sig = mcspi_dma->dma_rx_sync_dev;
- mcspi_dma->dma_rx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
+
+ mcspi_dma->dma_rx =
+ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+ &sig, &master->dev,
+ mcspi_dma->dma_rx_ch_name);
+
if (!mcspi_dma->dma_rx) {
dev_err(&spi->dev, "no RX DMA engine channel for McSPI\n");
return -EAGAIN;
}
sig = mcspi_dma->dma_tx_sync_dev;
- mcspi_dma->dma_tx = dma_request_channel(mask, omap_dma_filter_fn, &sig);
+ mcspi_dma->dma_tx =
+ dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
+ &sig, &master->dev,
+ mcspi_dma->dma_tx_ch_name);
+
if (!mcspi_dma->dma_tx) {
dev_err(&spi->dev, "no TX DMA engine channel for McSPI\n");
dma_release_channel(mcspi_dma->dma_rx);
@@ -1223,29 +1235,42 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
goto free_master;
for (i = 0; i < master->num_chipselect; i++) {
- char dma_ch_name[14];
+ char *dma_rx_ch_name = mcspi->dma_channels[i].dma_rx_ch_name;
+ char *dma_tx_ch_name = mcspi->dma_channels[i].dma_tx_ch_name;
struct resource *dma_res;
- sprintf(dma_ch_name, "rx%d", i);
- dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
- dma_ch_name);
- if (!dma_res) {
- dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
- status = -ENODEV;
- break;
- }
+ sprintf(dma_rx_ch_name, "rx%d", i);
+ if (!pdev->dev.of_node) {
+ dma_res =
+ platform_get_resource_byname(pdev,
+ IORESOURCE_DMA,
+ dma_rx_ch_name);
+ if (!dma_res) {
+ dev_dbg(&pdev->dev,
+ "cannot get DMA RX channel\n");
+ status = -ENODEV;
+ break;
+ }
- mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
- sprintf(dma_ch_name, "tx%d", i);
- dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
- dma_ch_name);
- if (!dma_res) {
- dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
- status = -ENODEV;
- break;
+ mcspi->dma_channels[i].dma_rx_sync_dev =
+ dma_res->start;
}
+ sprintf(dma_tx_ch_name, "tx%d", i);
+ if (!pdev->dev.of_node) {
+ dma_res =
+ platform_get_resource_byname(pdev,
+ IORESOURCE_DMA,
+ dma_tx_ch_name);
+ if (!dma_res) {
+ dev_dbg(&pdev->dev,
+ "cannot get DMA TX channel\n");
+ status = -ENODEV;
+ break;
+ }
- mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
+ mcspi->dma_channels[i].dma_tx_sync_dev =
+ dma_res->start;
+ }
}
if (status < 0)
--
1.7.9.5
^ permalink raw reply related
* [PATCH v7 07/10] dmaengine: add dma_request_slave_channel_compat()
From: Matt Porter @ 2013-02-01 18:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359742975-10421-1-git-send-email-mporter@ti.com>
Adds a dma_request_slave_channel_compat() wrapper which accepts
both the arguments from dma_request_channel() and
dma_request_slave_channel(). Based on whether the driver is
instantiated via DT, the appropriate channel request call will be
made.
This allows for a much cleaner migration of drivers to the
dmaengine DT API as platforms continue to be mixed between those
that boot using DT and those that do not.
Suggested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Matt Porter <mporter@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
include/linux/dmaengine.h | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index bfcdecb..17d8ffd 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -1001,6 +1001,22 @@ void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type);
struct dma_chan *net_dma_find_channel(void);
#define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
+#define dma_request_slave_channel_compat(mask, x, y, dev, name) \
+ __dma_request_slave_channel_compat(&(mask), x, y, dev, name)
+
+static inline struct dma_chan
+*__dma_request_slave_channel_compat(dma_cap_mask_t *mask, dma_filter_fn fn,
+ void *fn_param, struct device *dev,
+ char *name)
+{
+ struct dma_chan *chan;
+
+ chan = dma_request_slave_channel(dev, name);
+ if (chan)
+ return chan;
+
+ return __dma_request_channel(mask, fn, fn_param);
+}
/* --- Helper iov-locking functions --- */
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox