示例#1
0
文件: mobility.c 项目: MohdVara/linux
static int update_dt_node(u32 phandle, s32 scope)
{
	struct update_props_workarea *upwa;
	struct device_node *dn;
	struct property *prop = NULL;
	int i, rc, rtas_rc;
	char *prop_data;
	char *rtas_buf;
	int update_properties_token;
	u32 vd;

	update_properties_token = rtas_token("ibm,update-properties");
	if (update_properties_token == RTAS_UNKNOWN_SERVICE)
		return -EINVAL;

	rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
	if (!rtas_buf)
		return -ENOMEM;

	dn = of_find_node_by_phandle(phandle);
	if (!dn) {
		kfree(rtas_buf);
		return -ENOENT;
	}

	upwa = (struct update_props_workarea *)&rtas_buf[0];
	upwa->phandle = phandle;

	do {
		rtas_rc = mobility_rtas_call(update_properties_token, rtas_buf,
					scope);
		if (rtas_rc < 0)
			break;

		prop_data = rtas_buf + sizeof(*upwa);

		/* On the first call to ibm,update-properties for a node the
		 * the first property value descriptor contains an empty
		 * property name, the property value length encoded as u32,
		 * and the property value is the node path being updated.
		 */
		if (*prop_data == 0) {
			prop_data++;
			vd = *(u32 *)prop_data;
			prop_data += vd + sizeof(vd);
			upwa->nprops--;
		}

		for (i = 0; i < upwa->nprops; i++) {
			char *prop_name;

			prop_name = prop_data;
			prop_data += strlen(prop_name) + 1;
			vd = *(u32 *)prop_data;
			prop_data += sizeof(vd);

			switch (vd) {
			case 0x00000000:
				/* name only property, nothing to do */
				break;

			case 0x80000000:
				prop = of_find_property(dn, prop_name, NULL);
				of_remove_property(dn, prop);
				prop = NULL;
				break;

			default:
				rc = update_dt_property(dn, &prop, prop_name,
							vd, prop_data);
				if (rc) {
					printk(KERN_ERR "Could not update %s"
					       " property\n", prop_name);
				}

				prop_data += vd;
			}
		}
	} while (rtas_rc == 1);

	of_node_put(dn);
	kfree(rtas_buf);
	return 0;
}
示例#2
0
static void disable_serial_gpio(void)
{
	struct device_node *np_tx, *np_rx, *np_tx_def, *np_rx_def;
	struct property *pp;
	static u32 pin_func_val;
	static struct property pin_func = {
		.name = "qcom,pin-func",
		.value = &pin_func_val,
		.length = sizeof(pin_func_val),
	};
	static struct property output_low = {
		.name = "output-low",
		.value = NULL,
		.length = 0,
	};
	static struct property bias_disable = {
		.name = "bias-disable",
		.value = NULL,
		.length = 0,
	};

	np_tx = of_find_node_by_path(
			"/soc/pinctrl@fd510000/msm_gpio_4");
	if (!np_tx) {
		pr_err("couldn't find msm_gpio_4 node\n");
		return;
	}

	np_rx = of_find_node_by_path(
			"/soc/pinctrl@fd510000/msm_gpio_5");
	if (!np_rx) {
		pr_err("couldn't find msm_gpio_5 node\n");
		goto err0;
	}

	of_update_property(np_tx, &pin_func);
	of_update_property(np_rx, &pin_func);

	np_tx_def = of_find_node_by_name(np_tx, "default");
	if (!np_tx_def) {
		pr_err("couldn't find msm_gpio_4_def node\n");
		goto err1;
	}

	np_rx_def = of_find_node_by_name(np_rx, "default");
	if (!np_rx_def) {
		pr_err("couldn't find msm_gpio_5_def node\n");
		goto err2;
	}

	of_add_property(np_tx_def, &output_low);

	pp = of_find_property(np_rx_def, "bias-pull-up", NULL);
	if (pp) {
		of_remove_property(np_rx_def, pp);
		of_add_property(np_rx_def, &bias_disable);
	}
	of_add_property(np_rx_def, &output_low);

	of_node_put(np_rx_def);
err2:
	of_node_put(np_tx_def);
err1:
	of_node_put(np_rx);
err0:
	of_node_put(np_tx);
	return;
}

static int __init init_console_setup(void)
{
	if (need_serial_console) {
		pr_info("Adding %s%d as preferred console\n",
			CONSOLE_NAME, CONSOLE_IX);
		add_preferred_console(CONSOLE_NAME,
			CONSOLE_IX,
			CONSOLE_OPTIONS);
	} else {
		struct device_node *np;
		static struct property serial_con_status = {
			.name = "status",
			.value = "disabled",
			.length = sizeof("disabled"),
		};

		np = of_find_node_by_path("/soc/serial@f991e000");
		if (!np) {
			pr_err("couldn't find /soc/serial@f991e000 node\n");
			return -EINVAL;
		}

		pr_info("disabling %s node", np->full_name);
		of_update_property(np, &serial_con_status);
		of_node_put(np);
		disable_serial_gpio();
	}

	return 0;
}
early_initcall(init_console_setup);