Exemplo n.º 1
0
static int max8973_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
	struct max8973_regulator_platform_data *pdata;
	struct regulator_init_data *ridata;
	struct regulator_config config = { };
	struct regulator_dev *rdev;
	struct max8973_chip *max;
	bool pdata_from_dt = false;
	unsigned int chip_id;
	int ret;

	pdata = dev_get_platdata(&client->dev);

	if (!pdata && client->dev.of_node) {
		pdata = max8973_parse_dt(&client->dev);
		pdata_from_dt = true;
	}

	if (!pdata) {
		dev_err(&client->dev, "No Platform data");
		return -EIO;
	}

	if ((pdata->dvs_gpio == -EPROBE_DEFER) ||
		(pdata->enable_gpio == -EPROBE_DEFER))
		return -EPROBE_DEFER;

	max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL);
	if (!max)
		return -ENOMEM;

	max->regmap = devm_regmap_init_i2c(client, &max8973_regmap_config);
	if (IS_ERR(max->regmap)) {
		ret = PTR_ERR(max->regmap);
		dev_err(&client->dev, "regmap init failed, err %d\n", ret);
		return ret;
	}

	if (client->dev.of_node) {
		const struct of_device_id *match;

		match = of_match_device(of_match_ptr(of_max8973_match_tbl),
				&client->dev);
		if (!match)
			return -ENODATA;
		max->id = (u32)((uintptr_t)match->data);
	} else {
		max->id = id->driver_data;
	}

	ret = regmap_read(max->regmap, MAX8973_CHIPID1, &chip_id);
	if (ret < 0) {
		dev_err(&client->dev, "register CHIPID1 read failed, %d", ret);
		return ret;
	}

	dev_info(&client->dev, "CHIP-ID OTP: 0x%02x ID_M: 0x%02x\n",
			(chip_id >> 4) & 0xF, (chip_id >> 1) & 0x7);

	i2c_set_clientdata(client, max);
	max->ops = max8973_dcdc_ops;
	max->dev = &client->dev;
	max->desc.name = id->name;
	max->desc.id = 0;
	max->desc.ops = &max->ops;
	max->desc.type = REGULATOR_VOLTAGE;
	max->desc.owner = THIS_MODULE;
	max->desc.min_uV = MAX8973_MIN_VOLATGE;
	max->desc.uV_step = MAX8973_VOLATGE_STEP;
	max->desc.n_voltages = MAX8973_BUCK_N_VOLTAGE;

	max->dvs_gpio = (pdata->dvs_gpio) ? pdata->dvs_gpio : -EINVAL;
	max->enable_gpio = (pdata->enable_gpio) ? pdata->enable_gpio : -EINVAL;
	max->enable_external_control = pdata->enable_ext_control;
	max->curr_gpio_val = pdata->dvs_def_state;
	max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state;

	if (gpio_is_valid(max->enable_gpio))
		max->enable_external_control = true;

	max->lru_index[0] = max->curr_vout_reg;

	if (gpio_is_valid(max->dvs_gpio)) {
		int gpio_flags;
		int i;

		gpio_flags = (pdata->dvs_def_state) ?
				GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
		ret = devm_gpio_request_one(&client->dev, max->dvs_gpio,
				gpio_flags, "max8973-dvs");
		if (ret) {
			dev_err(&client->dev,
				"gpio_request for gpio %d failed, err = %d\n",
				max->dvs_gpio, ret);
			return ret;
		}

		/*
		 * Initialize the lru index with vout_reg id
		 * The index 0 will be most recently used and
		 * set with the max->curr_vout_reg */
		for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i)
			max->lru_index[i] = i;
		max->lru_index[0] = max->curr_vout_reg;
		max->lru_index[max->curr_vout_reg] = 0;
	}

	if (pdata_from_dt)
		pdata->reg_init_data = of_get_regulator_init_data(&client->dev,
					client->dev.of_node, &max->desc);

	ridata = pdata->reg_init_data;
	switch (max->id) {
	case MAX8973:
		if (!pdata->enable_ext_control) {
			max->desc.enable_reg = MAX8973_VOUT;
			max->desc.enable_mask = MAX8973_VOUT_ENABLE;
			max->ops.enable = regulator_enable_regmap;
			max->ops.disable = regulator_disable_regmap;
			max->ops.is_enabled = regulator_is_enabled_regmap;
			break;
		}

		if (gpio_is_valid(max->enable_gpio)) {
			config.ena_gpio_flags = GPIOF_OUT_INIT_LOW;
			if (ridata && (ridata->constraints.always_on ||
					ridata->constraints.boot_on))
				config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
			config.ena_gpio = max->enable_gpio;
		}
		break;

	case MAX77621:
		if (gpio_is_valid(max->enable_gpio)) {
			ret = devm_gpio_request_one(&client->dev,
					max->enable_gpio, GPIOF_OUT_INIT_HIGH,
					"max8973-en-gpio");
			if (ret) {
				dev_err(&client->dev,
					"gpio_request for gpio %d failed: %d\n",
					max->enable_gpio, ret);
				return ret;
			}
		}

		max->desc.enable_reg = MAX8973_VOUT;
		max->desc.enable_mask = MAX8973_VOUT_ENABLE;
		max->ops.enable = regulator_enable_regmap;
		max->ops.disable = regulator_disable_regmap;
		max->ops.is_enabled = regulator_is_enabled_regmap;
		break;
	default:
		break;
	}

	ret = max8973_init_dcdc(max, pdata);
	if (ret < 0) {
		dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret);
		return ret;
	}

	config.dev = &client->dev;
	config.init_data = pdata->reg_init_data;
	config.driver_data = max;
	config.of_node = client->dev.of_node;
	config.regmap = max->regmap;

	/* Register the regulators */
	rdev = devm_regulator_register(&client->dev, &max->desc, &config);
	if (IS_ERR(rdev)) {
		ret = PTR_ERR(rdev);
		dev_err(max->dev, "regulator register failed, err %d\n", ret);
		return ret;
	}

	return 0;
}
Exemplo n.º 2
0
static int tas571x_i2c_probe(struct i2c_client *client,
			     const struct i2c_device_id *id)
{
	struct tas571x_private *priv;
	struct device *dev = &client->dev;
	const struct of_device_id *of_id;
	int i, ret;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;
	i2c_set_clientdata(client, priv);

	of_id = of_match_device(tas571x_of_match, dev);
	if (of_id)
		priv->chip = of_id->data;
	else
		priv->chip = (void *) id->driver_data;

	priv->mclk = devm_clk_get(dev, "mclk");
	if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) {
		dev_err(dev, "Failed to request mclk: %ld\n",
			PTR_ERR(priv->mclk));
		return PTR_ERR(priv->mclk);
	}

	if (WARN_ON(priv->chip->num_supply_names > TAS571X_MAX_SUPPLIES))
		return -EINVAL;
	for (i = 0; i < priv->chip->num_supply_names; i++)
		priv->supplies[i].supply = priv->chip->supply_names[i];

	ret = devm_regulator_bulk_get(dev, priv->chip->num_supply_names,
				      priv->supplies);
	if (ret) {
		dev_err(dev, "Failed to get supplies: %d\n", ret);
		return ret;
	}
	ret = regulator_bulk_enable(priv->chip->num_supply_names,
				    priv->supplies);
	if (ret) {
		dev_err(dev, "Failed to enable supplies: %d\n", ret);
		return ret;
	}

	priv->regmap = devm_regmap_init(dev, NULL, client,
					priv->chip->regmap_config);
	if (IS_ERR(priv->regmap))
		return PTR_ERR(priv->regmap);

	priv->pdn_gpio = devm_gpiod_get_optional(dev, "pdn", GPIOD_OUT_LOW);
	if (IS_ERR(priv->pdn_gpio)) {
		dev_err(dev, "error requesting pdn_gpio: %ld\n",
			PTR_ERR(priv->pdn_gpio));
		return PTR_ERR(priv->pdn_gpio);
	}

	priv->reset_gpio = devm_gpiod_get_optional(dev, "reset",
						   GPIOD_OUT_HIGH);
	if (IS_ERR(priv->reset_gpio)) {
		dev_err(dev, "error requesting reset_gpio: %ld\n",
			PTR_ERR(priv->reset_gpio));
		return PTR_ERR(priv->reset_gpio);
	} else if (priv->reset_gpio) {
		/* pulse the active low reset line for ~100us */
		usleep_range(100, 200);
		gpiod_set_value(priv->reset_gpio, 0);
		usleep_range(13500, 20000);
	}

	ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0);
	if (ret)
		return ret;

	usleep_range(50000, 60000);

	memcpy(&priv->component_driver, &tas571x_component, sizeof(priv->component_driver));
	priv->component_driver.controls = priv->chip->controls;
	priv->component_driver.num_controls = priv->chip->num_controls;

	if (priv->chip->vol_reg_size == 2) {
		/*
		 * The master volume defaults to 0x3ff (mute), but we ignore
		 * (zero) the LSB because the hardware step size is 0.125 dB
		 * and TLV_DB_SCALE_ITEM has a resolution of 0.01 dB.
		 */
		ret = regmap_update_bits(priv->regmap, TAS571X_MVOL_REG, 1, 0);
		if (ret)
			return ret;
	}

	return devm_snd_soc_register_component(&client->dev,
				      &priv->component_driver,
				      &tas571x_dai, 1);
}
Exemplo n.º 3
0
static int palmas_regulators_probe(struct platform_device *pdev)
{
	struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
	struct palmas_pmic_platform_data *pdata = dev_get_platdata(&pdev->dev);
	struct device_node *node = pdev->dev.of_node;
	struct palmas_pmic_driver_data *driver_data;
	struct regulator_config config = { };
	struct palmas_pmic *pmic;
	const char *pdev_name;
	const struct of_device_id *match;
	int ret = 0;
	unsigned int reg;

	match = of_match_device(of_match_ptr(of_palmas_match_tbl), &pdev->dev);

	if (!match)
		return -ENODATA;

	driver_data = (struct palmas_pmic_driver_data *)match->data;
	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
	if (!pdata)
		return -ENOMEM;

	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
	if (!pmic)
		return -ENOMEM;

	if (of_device_is_compatible(node, "ti,tps659038-pmic")) {
		palmas_generic_regs_info[PALMAS_REG_REGEN2].ctrl_addr =
							TPS659038_REGEN2_CTRL;
		palmas_ddata.has_regen3 = false;
	}

	pmic->dev = &pdev->dev;
	pmic->palmas = palmas;
	palmas->pmic = pmic;
	platform_set_drvdata(pdev, pmic);
	pmic->palmas->pmic_ddata = driver_data;

	ret = palmas_dt_to_pdata(&pdev->dev, node, pdata, driver_data);
	if (ret)
		return ret;

	ret = palmas_smps_read(palmas, PALMAS_SMPS_CTRL, &reg);
	if (ret)
		return ret;

	if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN) {
		pmic->smps123 = 1;
		pmic->smps12 = 1;
	}

	if (reg & PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN)
		pmic->smps457 = 1;

	config.regmap = palmas->regmap[REGULATOR_SLAVE];
	config.dev = &pdev->dev;
	config.driver_data = pmic;
	pdev_name = pdev->name;

	ret = driver_data->smps_register(pmic, driver_data, pdata, pdev_name,
					 config);
	if (ret)
		return ret;

	ret = driver_data->ldo_register(pmic, driver_data, pdata, pdev_name,
					config);

	return ret;
}
Exemplo n.º 4
0
static int fs_enet_probe(struct platform_device *ofdev)
{
	const struct of_device_id *match;
	struct net_device *ndev;
	struct fs_enet_private *fep;
	struct fs_platform_info *fpi;
	const u32 *data;
	const u8 *mac_addr;
	const char *phy_connection_type;
	int privsize, len, ret = -ENODEV;

	match = of_match_device(fs_enet_match, &ofdev->dev);
	if (!match)
		return -EINVAL;

	fpi = kzalloc(sizeof(*fpi), GFP_KERNEL);
	if (!fpi)
		return -ENOMEM;

	if (!IS_FEC(match)) {
		data = of_get_property(ofdev->dev.of_node, "fsl,cpm-command", &len);
		if (!data || len != 4)
			goto out_free_fpi;

		fpi->cp_command = *data;
	}

	fpi->rx_ring = 32;
	fpi->tx_ring = 32;
	fpi->rx_copybreak = 240;
	fpi->use_napi = 1;
	fpi->napi_weight = 17;
	fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
	if ((!fpi->phy_node) && (!of_get_property(ofdev->dev.of_node, "fixed-link",
						  NULL)))
		goto out_free_fpi;

	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
		phy_connection_type = of_get_property(ofdev->dev.of_node,
						"phy-connection-type", NULL);
		if (phy_connection_type && !strcmp("rmii", phy_connection_type))
			fpi->use_rmii = 1;
	}

	privsize = sizeof(*fep) +
	           sizeof(struct sk_buff **) *
	           (fpi->rx_ring + fpi->tx_ring);

	ndev = alloc_etherdev(privsize);
	if (!ndev) {
		ret = -ENOMEM;
		goto out_put;
	}

	SET_NETDEV_DEV(ndev, &ofdev->dev);
	dev_set_drvdata(&ofdev->dev, ndev);

	fep = netdev_priv(ndev);
	fep->dev = &ofdev->dev;
	fep->ndev = ndev;
	fep->fpi = fpi;
	fep->ops = match->data;

	ret = fep->ops->setup_data(ndev);
	if (ret)
		goto out_free_dev;

	fep->rx_skbuff = (struct sk_buff **)&fep[1];
	fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;

	spin_lock_init(&fep->lock);
	spin_lock_init(&fep->tx_lock);

	mac_addr = of_get_mac_address(ofdev->dev.of_node);
	if (mac_addr)
		memcpy(ndev->dev_addr, mac_addr, 6);

	ret = fep->ops->allocate_bd(ndev);
	if (ret)
		goto out_cleanup_data;

	fep->rx_bd_base = fep->ring_base;
	fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;

	fep->tx_ring = fpi->tx_ring;
	fep->rx_ring = fpi->rx_ring;

	ndev->netdev_ops = &fs_enet_netdev_ops;
	ndev->watchdog_timeo = 2 * HZ;
	if (fpi->use_napi)
		netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi,
		               fpi->napi_weight);

	ndev->ethtool_ops = &fs_ethtool_ops;

	init_timer(&fep->phy_timer_list);

	netif_carrier_off(ndev);

	ret = register_netdev(ndev);
	if (ret)
		goto out_free_bd;

	pr_info("%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr);

	return 0;

out_free_bd:
	fep->ops->free_bd(ndev);
out_cleanup_data:
	fep->ops->cleanup_data(ndev);
out_free_dev:
	free_netdev(ndev);
	dev_set_drvdata(&ofdev->dev, NULL);
out_put:
	of_node_put(fpi->phy_node);
out_free_fpi:
	kfree(fpi);
	return ret;
}
Exemplo n.º 5
0
static int tegra_uart_probe(struct platform_device *pdev)
{
	struct tegra_uart_port *tup;
	struct uart_port *u;
	struct resource *resource;
	int ret;
	const struct tegra_uart_chip_data *cdata;
	const struct of_device_id *match;

	match = of_match_device(tegra_uart_of_match, &pdev->dev);
	if (!match) {
		dev_err(&pdev->dev, "Error: No device match found\n");
		return -ENODEV;
	}
	cdata = match->data;

	tup = devm_kzalloc(&pdev->dev, sizeof(*tup), GFP_KERNEL);
	if (!tup) {
		dev_err(&pdev->dev, "Failed to allocate memory for tup\n");
		return -ENOMEM;
	}

	ret = tegra_uart_parse_dt(pdev, tup);
	if (ret < 0)
		return ret;

	u = &tup->uport;
	u->dev = &pdev->dev;
	u->ops = &tegra_uart_ops;
	u->type = PORT_TEGRA;
	u->fifosize = 32;
	tup->cdata = cdata;

	platform_set_drvdata(pdev, tup);
	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!resource) {
		dev_err(&pdev->dev, "No IO memory resource\n");
		return -ENODEV;
	}

	u->mapbase = resource->start;
	u->membase = devm_ioremap_resource(&pdev->dev, resource);
	if (IS_ERR(u->membase))
		return PTR_ERR(u->membase);

	tup->uart_clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(tup->uart_clk)) {
		dev_err(&pdev->dev, "Couldn't get the clock\n");
		return PTR_ERR(tup->uart_clk);
	}

	tup->rst = devm_reset_control_get_exclusive(&pdev->dev, "serial");
	if (IS_ERR(tup->rst)) {
		dev_err(&pdev->dev, "Couldn't get the reset\n");
		return PTR_ERR(tup->rst);
	}

	u->iotype = UPIO_MEM32;
	ret = platform_get_irq(pdev, 0);
	if (ret < 0) {
		dev_err(&pdev->dev, "Couldn't get IRQ\n");
		return ret;
	}
	u->irq = ret;
	u->regshift = 2;
	ret = uart_add_one_port(&tegra_uart_driver, u);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to add uart port, err %d\n", ret);
		return ret;
	}
	return ret;
}
Exemplo n.º 6
0
static int act8846_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
	struct act8846 *act8846;	
	struct act8846_board *pdev ;
	const struct of_device_id *match;
	struct regulator_config config = { };
	struct regulator_dev *act_rdev;
	struct regulator_init_data *reg_data;
	const char *rail_name = NULL;
	int ret,i=0;
	
	printk("%s,line=%d\n", __func__,__LINE__);	

	if (i2c->dev.of_node) {
		match = of_match_device(act8846_of_match, &i2c->dev);
		if (!match) {
			printk("Failed to find matching dt id\n");
			return -EINVAL;
		}
	}

	act8846 = devm_kzalloc(&i2c->dev,sizeof(struct act8846), GFP_KERNEL);
	if (act8846 == NULL) {
		ret = -ENOMEM;		
		goto err;
	}
	act8846->i2c = i2c;
	act8846->dev = &i2c->dev;
	i2c_set_clientdata(i2c, act8846);
	g_act8846 = act8846;
	
	act8846->regmap = devm_regmap_init_i2c(i2c, &act8846_regmap_config);
	if (IS_ERR(act8846->regmap)) {
		ret = PTR_ERR(act8846->regmap);
		printk("regmap initialization failed: %d\n", ret);
		return ret;
	}
	
	mutex_init(&act8846->io_lock);	

	ret = act8846_reg_read(act8846,0x22);
	if ((ret < 0) || (ret == 0xff)){
		printk("The device is not act8846 %x \n",ret);
		goto err;
	}

	ret = act8846_set_bits(act8846, 0xf4,(0x1<<7),(0x0<<7));
	if (ret < 0) {
		printk("act8846 set 0xf4 error!\n");
		goto err;
	}

	if (act8846->dev->of_node)
		pdev = act8846_parse_dt(act8846);

	#ifdef CONFIG_OF
	act8846->pmic_hold_gpio = pdev->pmic_hold_gpio;
	if (act8846->pmic_hold_gpio) {
			ret = gpio_request(act8846->pmic_hold_gpio, "act8846_pmic_hold");
			if (ret < 0) {
				dev_err(act8846->dev,"Failed to request gpio %d with ret:""%d\n",	act8846->pmic_hold_gpio, ret);
				return IRQ_NONE;
			}
			gpio_direction_output(act8846->pmic_hold_gpio,1);
			ret = gpio_get_value(act8846->pmic_hold_gpio);
	//		gpio_free(act8846->pmic_hold_gpio);
			printk("%s: act8846_pmic_hold=%x\n", __func__, ret);
	}
	#endif
	
	/******************************set sleep vol & dcdc mode******************/
	#ifdef CONFIG_OF
	act8846->pmic_sleep_gpio = pdev->pmic_sleep_gpio;
	if (act8846->pmic_sleep_gpio) {
			ret = gpio_request(act8846->pmic_sleep_gpio, "act8846_pmic_sleep");
			if (ret < 0) {
				dev_err(act8846->dev,"Failed to request gpio %d with ret:""%d\n",	act8846->pmic_sleep_gpio, ret);
				return IRQ_NONE;
			}
			gpio_direction_output(act8846->pmic_sleep_gpio,1);
			ret = gpio_get_value(act8846->pmic_sleep_gpio);
			gpio_free(act8846->pmic_sleep_gpio);
			printk("%s: act8846_pmic_sleep=%x\n", __func__, ret);
	}
	#endif
	
    /****************************set cpu_det high **************************/
    #ifdef CONFIG_OF
    act8846->pmic_cpu_det_gpio = pdev->pmic_cpu_det_gpio;
    if (act8846->pmic_cpu_det_gpio) {
            ret = gpio_request(act8846->pmic_cpu_det_gpio, "act8846_pmic_cpu_det");
            if (ret < 0) {
                dev_err(act8846->dev,"Failed to request gpio %d with ret:""%d\n",       act8846->pmic_cpu_det_gpio, ret);
                return IRQ_NONE;
            }
            gpio_direction_output(act8846->pmic_cpu_det_gpio, 1);
            ret = gpio_get_value(act8846->pmic_cpu_det_gpio);
            printk("%s: act8846_pmic_cpu_det_gpio=%x\n", __func__, ret);
    }
    #endif
    
    #ifdef CONFIG_OF
    act8846->pmic_usb_hub_reset_gpio = pdev->pmic_usb_hub_reset_gpio;
    if (act8846->pmic_usb_hub_reset_gpio) {
            ret = gpio_request(act8846->pmic_usb_hub_reset_gpio, "act8846_pmic_usb_hub_reset_gpio");
            if (ret < 0) {
                dev_err(act8846->dev,"Failed to request gpio %d with ret:""%d\n",       act8846->pmic_usb_hub_reset_gpio, ret);
                return IRQ_NONE;
            }
            gpio_direction_output(act8846->pmic_usb_hub_reset_gpio, 1);
            ret = gpio_get_value(act8846->pmic_usb_hub_reset_gpio);
            printk("%s: act8846_pmic_usb_hub_reset_gpio=%x\n", __func__, ret);
    }
    #endif
	
	if (pdev) {
		act8846->num_regulators = act8846_NUM_REGULATORS;
		act8846->rdev = kcalloc(act8846_NUM_REGULATORS,sizeof(struct regulator_dev *), GFP_KERNEL);
		if (!act8846->rdev) {
			return -ENOMEM;
		}
		/* Instantiate the regulators */
		for (i = 0; i < act8846_NUM_REGULATORS; i++) {
		reg_data = pdev->act8846_init_data[i];
		if (!reg_data)
			continue;
		config.dev = act8846->dev;
		config.driver_data = act8846;
		config.regmap = act8846->regmap;
		if (act8846->dev->of_node)
			config.of_node = pdev->of_node[i];

			if (reg_data && reg_data->constraints.name)
				rail_name = reg_data->constraints.name;
			else
				rail_name = regulators[i].name;
			reg_data->supply_regulator = rail_name;
	
		config.init_data =reg_data;
		
		act_rdev = regulator_register(&regulators[i],&config);
		if (IS_ERR(act_rdev)) {
			printk("failed to register %d regulator\n",i);
		goto err;
		}
		act8846->rdev[i] = act_rdev;
		}
	}

	if (pdev->pm_off && !pm_power_off) {
		pm_power_off = act8846_device_shutdown;
	}
	
	#ifdef CONFIG_HAS_EARLYSUSPEND
	act8846->act8846_suspend.suspend = act8846_early_suspend,
	act8846->act8846_suspend.resume = act8846_late_resume,
	act8846->act8846_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1,
	register_early_suspend(&act8846->act8846_suspend);
	#endif	

	return 0;

err:
	return ret;	

}
Exemplo n.º 7
0
static int vfe_probe(struct platform_device *pdev)
{
	struct vfe_device *vfe_dev;
	/*struct msm_cam_subdev_info sd_info;*/
	const struct of_device_id *match_dev;
	int rc = 0;

	struct msm_iova_partition vfe_partition = {
		.start = SZ_128K,
		.size = SZ_2G - SZ_128K,
	};
	struct msm_iova_layout vfe_layout = {
		.partitions = &vfe_partition,
		.npartitions = 1,
		.client_name = "vfe",
		.domain_flags = 0,
	};

	vfe_dev = kzalloc(sizeof(struct vfe_device), GFP_KERNEL);
	if (!vfe_dev) {
		pr_err("%s: no enough memory\n", __func__);
		rc = -ENOMEM;
		goto end;
	}
	vfe_dev->stats = kzalloc(sizeof(struct msm_isp_statistics), GFP_KERNEL);
	if (!vfe_dev->stats) {
		pr_err("%s: no enough memory\n", __func__);
		rc = -ENOMEM;
		goto probe_fail1;
	}

	vfe_dev->ub_info = kzalloc(sizeof(struct msm_isp_ub_info), GFP_KERNEL);
	if (!vfe_dev->ub_info) {
		pr_err("%s: no enough memory\n", __func__);
		rc = -ENOMEM;
		goto probe_fail2;
	}
	if (pdev->dev.of_node) {
		of_property_read_u32((&pdev->dev)->of_node,
			"cell-index", &pdev->id);
		match_dev = of_match_device(msm_vfe_dt_match, &pdev->dev);
		if (!match_dev) {
			pr_err("%s: No vfe hardware info\n", __func__);
			rc = -EINVAL;
			goto probe_fail3;
		}
		vfe_dev->hw_info =
			(struct msm_vfe_hardware_info *) match_dev->data;
	} else {
		vfe_dev->hw_info = (struct msm_vfe_hardware_info *)
			platform_get_device_id(pdev)->driver_data;
	}

	if (!vfe_dev->hw_info) {
		pr_err("%s: No vfe hardware info\n", __func__);
		rc = -EINVAL;
		goto probe_fail3;
	}
	ISP_DBG("%s: device id = %d\n", __func__, pdev->id);

	vfe_dev->pdev = pdev;
	vfe_dev->dual_vfe_res = &dualvfe;
	vfe_dev->dual_vfe_res->axi_data[vfe_dev->pdev->id] =
		&vfe_dev->axi_data;
	vfe_dev->dual_vfe_res->stats_data[vfe_dev->pdev->id] =
		&vfe_dev->stats_data;

	rc = vfe_dev->hw_info->vfe_ops.core_ops.get_platform_data(vfe_dev);
	if (rc < 0) {
		pr_err("%s: failed to get platform resources\n", __func__);
		rc = -ENOMEM;
		goto probe_fail3;
	}

	INIT_LIST_HEAD(&vfe_dev->tasklet_q);
	tasklet_init(&vfe_dev->vfe_tasklet,
		msm_isp_do_tasklet, (unsigned long)vfe_dev);

	/* init hardware will enable it back */
	tasklet_disable(&vfe_dev->vfe_tasklet);
	v4l2_subdev_init(&vfe_dev->subdev.sd, vfe_dev->hw_info->subdev_ops);
	vfe_dev->subdev.sd.internal_ops =
		vfe_dev->hw_info->subdev_internal_ops;
	snprintf(vfe_dev->subdev.sd.name,
		ARRAY_SIZE(vfe_dev->subdev.sd.name),
		"vfe");
	vfe_dev->subdev.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	vfe_dev->subdev.sd.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
	v4l2_set_subdevdata(&vfe_dev->subdev.sd, vfe_dev);
	platform_set_drvdata(pdev, &vfe_dev->subdev.sd);
	mutex_init(&vfe_dev->realtime_mutex);
	mutex_init(&vfe_dev->core_mutex);
	mutex_init(&vfe_dev->buf_mgr_mutex);
	spin_lock_init(&vfe_dev->tasklet_lock);
	spin_lock_init(&vfe_dev->shared_data_lock);
	spin_lock_init(&vfe_dev->reg_update_lock);
	spin_lock_init(&vfe_dev->shared_cfg_reg_lock); //LGE_CHANGE, 20150609, Change spin_lock for watchodog case using shard_data_lock, changhwan.kang.kang
	spin_lock_init(&req_history_lock);
	media_entity_init(&vfe_dev->subdev.sd.entity, 0, NULL, 0);
	vfe_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
	vfe_dev->subdev.sd.entity.group_id = MSM_CAMERA_SUBDEV_VFE;
	vfe_dev->subdev.sd.entity.name = pdev->name;
	vfe_dev->subdev.close_seq = MSM_SD_CLOSE_1ST_CATEGORY | 0x2;
	rc = msm_sd_register(&vfe_dev->subdev);
	if (rc != 0) {
		pr_err("%s: msm_sd_register error = %d\n", __func__, rc);
		goto probe_fail3;
	}

	msm_isp_v4l2_subdev_fops.owner = v4l2_subdev_fops.owner;
	msm_isp_v4l2_subdev_fops.open = v4l2_subdev_fops.open;
	msm_isp_v4l2_subdev_fops.release = v4l2_subdev_fops.release;
	msm_isp_v4l2_subdev_fops.poll = v4l2_subdev_fops.poll;

	vfe_dev->subdev.sd.devnode->fops = &msm_isp_v4l2_subdev_fops;

	vfe_dev->buf_mgr = &vfe_buf_mgr;
	v4l2_subdev_notify(&vfe_dev->subdev.sd,
		MSM_SD_NOTIFY_REQ_CB, &vfe_vb2_ops);
	rc = msm_isp_create_isp_buf_mgr(vfe_dev->buf_mgr,
		&vfe_vb2_ops, &vfe_layout);
	if (rc < 0) {
		pr_err("%s: Unable to create buffer manager\n", __func__);
		rc = -EINVAL;
		goto probe_fail3;
	}
	/* create secure context banks*/
	if (vfe_dev->hw_info->num_iommu_secure_ctx) {
		/*secure vfe layout*/
		struct msm_iova_layout vfe_secure_layout = {
			.partitions = &vfe_partition,
			.npartitions = 1,
			.client_name = "vfe_secure",
			.domain_flags = 0,
			.is_secure = MSM_IOMMU_DOMAIN_SECURE,
		};
		rc = msm_isp_create_secure_domain(vfe_dev->buf_mgr,
			&vfe_secure_layout);
		if (rc < 0) {
			pr_err("%s: fail to create secure domain\n", __func__);
			msm_sd_unregister(&vfe_dev->subdev);
			rc = -EINVAL;
			goto probe_fail3;
		}
	}
	msm_isp_enable_debugfs(vfe_dev, msm_isp_bw_request_history);
	vfe_dev->buf_mgr->ops->register_ctx(vfe_dev->buf_mgr,
		&vfe_dev->iommu_ctx[0], &vfe_dev->iommu_secure_ctx[0],
		vfe_dev->hw_info->num_iommu_ctx,
		vfe_dev->hw_info->num_iommu_secure_ctx);

	vfe_dev->buf_mgr->init_done = 1;
	vfe_dev->vfe_open_cnt = 0;
	return rc;

probe_fail3:
	kfree(vfe_dev->ub_info);
probe_fail2:
	kfree(vfe_dev->stats);
probe_fail1:
	kfree(vfe_dev);
end:
	return rc;
}

static struct platform_driver vfe_driver = {
	.probe = vfe_probe,
	.driver = {
		.name = "msm_vfe",
		.owner = THIS_MODULE,
		.of_match_table = msm_vfe_dt_match,
	},
	.id_table = msm_vfe_dev_id,
};

static int __init msm_vfe_init_module(void)
{
	return platform_driver_register(&vfe_driver);
}

static void __exit msm_vfe_exit_module(void)
{
	platform_driver_unregister(&vfe_driver);
}

module_init(msm_vfe_init_module);
module_exit(msm_vfe_exit_module);
MODULE_DESCRIPTION("MSM VFE driver");
MODULE_LICENSE("GPL v2");
Exemplo n.º 8
0
static int sdhci_pxav2_probe(struct platform_device *pdev)
{
	struct sdhci_pltfm_host *pltfm_host;
	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
	struct device *dev = &pdev->dev;
	struct sdhci_host *host = NULL;
	const struct of_device_id *match;

	int ret;
	struct clk *clk;

	host = sdhci_pltfm_init(pdev, NULL, 0);
	if (IS_ERR(host))
		return PTR_ERR(host);

	pltfm_host = sdhci_priv(host);
	pltfm_host->priv = NULL;

	clk = clk_get(dev, "PXA-SDHCLK");
	if (IS_ERR(clk)) {
		dev_err(dev, "failed to get io clock\n");
		ret = PTR_ERR(clk);
		goto err_clk_get;
	}
	pltfm_host->clk = clk;
	clk_prepare_enable(clk);

	host->quirks = SDHCI_QUIRK_BROKEN_ADMA
		| SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
		| SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;

	match = of_match_device(of_match_ptr(sdhci_pxav2_of_match), &pdev->dev);
	if (match) {
		pdata = pxav2_get_mmc_pdata(dev);
	}
	if (pdata) {
		if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
			/* on-chip device */
			host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
			host->mmc->caps |= MMC_CAP_NONREMOVABLE;
		}

		/* If slot design supports 8 bit data, indicate this to MMC. */
		if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
			host->mmc->caps |= MMC_CAP_8_BIT_DATA;

		if (pdata->quirks)
			host->quirks |= pdata->quirks;
		if (pdata->host_caps)
			host->mmc->caps |= pdata->host_caps;
		if (pdata->pm_caps)
			host->mmc->pm_caps |= pdata->pm_caps;
	}

	host->ops = &pxav2_sdhci_ops;

	ret = sdhci_add_host(host);
	if (ret) {
		dev_err(&pdev->dev, "failed to add host\n");
		goto err_add_host;
	}

	platform_set_drvdata(pdev, host);

	return 0;

err_add_host:
	clk_disable_unprepare(clk);
	clk_put(clk);
err_clk_get:
	sdhci_pltfm_free(pdev);
	return ret;
}
Exemplo n.º 9
0
static int __devinit sdhci_of_probe(struct platform_device *ofdev)
{
	const struct of_device_id *match;
	struct device_node *np = ofdev->dev.of_node;
	struct sdhci_of_data *sdhci_of_data;
	struct sdhci_host *host;
	struct sdhci_of_host *of_host;
	const __be32 *clk;
	int size;
	int ret;

	match = of_match_device(sdhci_of_match, &ofdev->dev);
	if (!match)
		return -EINVAL;
	sdhci_of_data = match->data;

	if (!of_device_is_available(np))
		return -ENODEV;

	host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host));
	if (IS_ERR(host))
		return -ENOMEM;

	of_host = sdhci_priv(host);
	dev_set_drvdata(&ofdev->dev, host);

	host->ioaddr = of_iomap(np, 0);
	if (!host->ioaddr) {
		ret = -ENOMEM;
		goto err_addr_map;
	}

	host->irq = irq_of_parse_and_map(np, 0);
	if (!host->irq) {
		ret = -EINVAL;
		goto err_no_irq;
	}

	host->hw_name = dev_name(&ofdev->dev);
	if (sdhci_of_data) {
		host->quirks = sdhci_of_data->quirks;
		host->ops = &sdhci_of_data->ops;
	}

	if (of_get_property(np, "sdhci,auto-cmd12", NULL))
		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;


	if (of_get_property(np, "sdhci,1-bit-only", NULL))
		host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;

	if (sdhci_of_wp_inverted(np))
		host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;

	clk = of_get_property(np, "clock-frequency", &size);
	if (clk && size == sizeof(*clk) && *clk)
		of_host->clock = be32_to_cpup(clk);

	ret = sdhci_add_host(host);
	if (ret)
		goto err_add_host;

	return 0;

err_add_host:
	irq_dispose_mapping(host->irq);
err_no_irq:
	iounmap(host->ioaddr);
err_addr_map:
	sdhci_free_host(host);
	return ret;
}
Exemplo n.º 10
0
static int rcar_du_probe(struct platform_device *pdev)
{
    struct device_node *np = pdev->dev.of_node;
    struct rcar_du_device *rcdu;
    struct drm_connector *connector;
    struct drm_device *ddev;
    struct resource *mem;
    int ret;

    if (np == NULL) {
        dev_err(&pdev->dev, "no device tree node\n");
        return -ENODEV;
    }

    /* Allocate and initialize the DRM and R-Car device structures. */
    rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
    if (rcdu == NULL)
        return -ENOMEM;

    init_waitqueue_head(&rcdu->commit.wait);

    rcdu->dev = &pdev->dev;
    rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;

    ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
    if (!ddev)
        return -ENOMEM;

    drm_dev_set_unique(ddev, dev_name(&pdev->dev));

    rcdu->ddev = ddev;
    ddev->dev_private = rcdu;

    platform_set_drvdata(pdev, rcdu);

    /* I/O resources */
    mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
    if (IS_ERR(rcdu->mmio)) {
        ret = PTR_ERR(rcdu->mmio);
        goto error;
    }

    /* Initialize vertical blanking interrupts handling. Start with vblank
     * disabled for all CRTCs.
     */
    ret = drm_vblank_init(ddev, (1 << rcdu->info->num_crtcs) - 1);
    if (ret < 0) {
        dev_err(&pdev->dev, "failed to initialize vblank\n");
        goto error;
    }

    /* DRM/KMS objects */
    ret = rcar_du_modeset_init(rcdu);
    if (ret < 0) {
        dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret);
        goto error;
    }

    ddev->irq_enabled = 1;

    /* Register the DRM device with the core and the connectors with
     * sysfs.
     */
    ret = drm_dev_register(ddev, 0);
    if (ret)
        goto error;

    mutex_lock(&ddev->mode_config.mutex);
    drm_for_each_connector(connector, ddev) {
        ret = drm_connector_register(connector);
        if (ret < 0)
            break;
    }
Exemplo n.º 11
0
static int of_platform_serial_probe(struct platform_device *ofdev)
{
	const struct of_device_id *match;
	struct of_serial_info *info;
	struct uart_port port;
	int port_type;
	int ret;

	match = of_match_device(of_platform_serial_table, &ofdev->dev);
	if (!match)
		return -EINVAL;

	if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
		return -EBUSY;

	info = kzalloc(sizeof(*info), GFP_KERNEL);
	if (info == NULL)
		return -ENOMEM;

	port_type = (unsigned long)match->data;
	ret = of_platform_serial_setup(ofdev, port_type, &port, info);
	if (ret)
		goto out;

	switch (port_type) {
	case PORT_8250 ... PORT_MAX_8250:
	{
		u32 tx_threshold;
		struct uart_8250_port port8250;
		memset(&port8250, 0, sizeof(port8250));
		port8250.port = port;

		if (port.fifosize)
			port8250.capabilities = UART_CAP_FIFO;

		/* Check for TX FIFO threshold & set tx_loadsz */
		if ((of_property_read_u32(ofdev->dev.of_node, "tx-threshold",
					  &tx_threshold) == 0) &&
		    (tx_threshold < port.fifosize))
			port8250.tx_loadsz = port.fifosize - tx_threshold;

		if (of_property_read_bool(ofdev->dev.of_node,
					  "auto-flow-control"))
			port8250.capabilities |= UART_CAP_AFE;

		ret = serial8250_register_8250_port(&port8250);
		break;
	}
	default:
		/* need to add code for these */
	case PORT_UNKNOWN:
		dev_info(&ofdev->dev, "Unknown serial port found, ignored\n");
		ret = -ENODEV;
		break;
	}
	if (ret < 0)
		goto out;

	info->type = port_type;
	info->line = ret;
	platform_set_drvdata(ofdev, info);
	return 0;
out:
	kfree(info);
	irq_dispose_mapping(port.irq);
	return ret;
}
Exemplo n.º 12
0
static int spi_imx_probe(struct platform_device *pdev)
{
    struct device_node *np = pdev->dev.of_node;
    const struct of_device_id *of_id =
        of_match_device(spi_imx_dt_ids, &pdev->dev);
    struct spi_imx_master *mxc_platform_info =
        dev_get_platdata(&pdev->dev);
    struct spi_master *master;
    struct spi_imx_data *spi_imx;
    struct resource *res;
    struct pinctrl *pinctrl;
    int i, ret, num_cs;

    if (!np && !mxc_platform_info) {
        dev_err(&pdev->dev, "can't get the platform data\n");
        return -EINVAL;
    }

    ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs);
    if (ret < 0) {
        if (mxc_platform_info)
            num_cs = mxc_platform_info->num_chipselect;
        else
            return ret;
    }

    master = spi_alloc_master(&pdev->dev,
                              sizeof(struct spi_imx_data) + sizeof(int) * num_cs);
    if (!master)
        return -ENOMEM;

    platform_set_drvdata(pdev, master);

    master->bus_num = pdev->id;
    master->num_chipselect = num_cs;

    spi_imx = spi_master_get_devdata(master);
    spi_imx->bitbang.master = spi_master_get(master);

    for (i = 0; i < master->num_chipselect; i++) {
        int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
        if (!gpio_is_valid(cs_gpio) && mxc_platform_info)
            cs_gpio = mxc_platform_info->chipselect[i];

        spi_imx->chipselect[i] = cs_gpio;
        if (!gpio_is_valid(cs_gpio))
            continue;

        ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME);
        if (ret) {
            dev_err(&pdev->dev, "can't get cs gpios\n");
            goto out_gpio_free;
        }
    }

    spi_imx->bitbang.chipselect = spi_imx_chipselect;
    spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
    spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
    spi_imx->bitbang.master->setup = spi_imx_setup;
    spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
    spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;

    init_completion(&spi_imx->xfer_done);

    spi_imx->devtype_data = of_id ? of_id->data :
                            (struct spi_imx_devtype_data *) pdev->id_entry->driver_data;

    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (!res) {
        dev_err(&pdev->dev, "can't get platform resource\n");
        ret = -ENOMEM;
        goto out_gpio_free;
    }

    if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
        dev_err(&pdev->dev, "request_mem_region failed\n");
        ret = -EBUSY;
        goto out_gpio_free;
    }

    spi_imx->base = ioremap(res->start, resource_size(res));
    if (!spi_imx->base) {
        ret = -EINVAL;
        goto out_release_mem;
    }

    spi_imx->irq = platform_get_irq(pdev, 0);
    if (spi_imx->irq < 0) {
        ret = -EINVAL;
        goto out_iounmap;
    }

    ret = request_irq(spi_imx->irq, spi_imx_isr, 0, DRIVER_NAME, spi_imx);
    if (ret) {
        dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret);
        goto out_iounmap;
    }

    pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
    if (IS_ERR(pinctrl)) {
        ret = PTR_ERR(pinctrl);
        goto out_free_irq;
    }

    spi_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
    if (IS_ERR(spi_imx->clk_ipg)) {
        ret = PTR_ERR(spi_imx->clk_ipg);
        goto out_free_irq;
    }

    spi_imx->clk_per = devm_clk_get(&pdev->dev, "per");
    if (IS_ERR(spi_imx->clk_per)) {
        ret = PTR_ERR(spi_imx->clk_per);
        goto out_free_irq;
    }

    clk_prepare_enable(spi_imx->clk_per);
    clk_prepare_enable(spi_imx->clk_ipg);

    spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per);

    spi_imx->devtype_data->reset(spi_imx);

    spi_imx->devtype_data->intctrl(spi_imx, 0);

    master->dev.of_node = pdev->dev.of_node;
    ret = spi_bitbang_start(&spi_imx->bitbang);
    if (ret) {
        dev_err(&pdev->dev, "bitbang start failed with %d\n", ret);
        goto out_clk_put;
    }

    dev_info(&pdev->dev, "probed\n");

    return ret;

out_clk_put:
    clk_disable_unprepare(spi_imx->clk_per);
    clk_disable_unprepare(spi_imx->clk_ipg);
out_free_irq:
    free_irq(spi_imx->irq, spi_imx);
out_iounmap:
    iounmap(spi_imx->base);
out_release_mem:
    release_mem_region(res->start, resource_size(res));
out_gpio_free:
    while (--i >= 0) {
        if (gpio_is_valid(spi_imx->chipselect[i]))
            gpio_free(spi_imx->chipselect[i]);
    }
    spi_master_put(master);
    kfree(master);
    platform_set_drvdata(pdev, NULL);
    return ret;
}
Exemplo n.º 13
0
static int mmp_tdma_probe(struct platform_device *pdev)
{
	enum mmp_tdma_type type;
	const struct of_device_id *of_id;
	struct mmp_tdma_device *tdev;
	struct resource *iores;
	int i, ret;
	int irq = 0, irq_num = 0;
	int chan_num = TDMA_CHANNEL_NUM;
	struct gen_pool *pool = NULL;

	of_id = of_match_device(mmp_tdma_dt_ids, &pdev->dev);
	if (of_id)
		type = (enum mmp_tdma_type) of_id->data;
	else
		type = platform_get_device_id(pdev)->driver_data;

	/* always have couple channels */
	tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
	if (!tdev)
		return -ENOMEM;

	tdev->dev = &pdev->dev;

	for (i = 0; i < chan_num; i++) {
		if (platform_get_irq(pdev, i) > 0)
			irq_num++;
	}

	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	tdev->base = devm_ioremap_resource(&pdev->dev, iores);
	if (IS_ERR(tdev->base))
		return PTR_ERR(tdev->base);

	INIT_LIST_HEAD(&tdev->device.channels);

	if (pdev->dev.of_node)
		pool = of_get_named_gen_pool(pdev->dev.of_node, "asram", 0);
	else
		pool = sram_get_gpool("asram");
	if (!pool) {
		dev_err(&pdev->dev, "asram pool not available\n");
		return -ENOMEM;
	}

	if (irq_num != chan_num) {
		irq = platform_get_irq(pdev, 0);
		ret = devm_request_irq(&pdev->dev, irq,
			mmp_tdma_int_handler, 0, "tdma", tdev);
		if (ret)
			return ret;
	}

	/* initialize channel parameters */
	for (i = 0; i < chan_num; i++) {
		irq = (irq_num != chan_num) ? 0 : platform_get_irq(pdev, i);
		ret = mmp_tdma_chan_init(tdev, i, irq, type, pool);
		if (ret)
			return ret;
	}

	dma_cap_set(DMA_SLAVE, tdev->device.cap_mask);
	dma_cap_set(DMA_CYCLIC, tdev->device.cap_mask);
	tdev->device.dev = &pdev->dev;
	tdev->device.device_alloc_chan_resources =
					mmp_tdma_alloc_chan_resources;
	tdev->device.device_free_chan_resources =
					mmp_tdma_free_chan_resources;
	tdev->device.device_prep_dma_cyclic = mmp_tdma_prep_dma_cyclic;
	tdev->device.device_tx_status = mmp_tdma_tx_status;
	tdev->device.device_issue_pending = mmp_tdma_issue_pending;
	tdev->device.device_config = mmp_tdma_config;
	tdev->device.device_pause = mmp_tdma_pause_chan;
	tdev->device.device_resume = mmp_tdma_resume_chan;
	tdev->device.device_terminate_all = mmp_tdma_terminate_all;
	tdev->device.copy_align = TDMA_ALIGNMENT;

	dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
	platform_set_drvdata(pdev, tdev);

	ret = dma_async_device_register(&tdev->device);
	if (ret) {
		dev_err(tdev->device.dev, "unable to register\n");
		return ret;
	}

	if (pdev->dev.of_node) {
		ret = of_dma_controller_register(pdev->dev.of_node,
							mmp_tdma_xlate, tdev);
		if (ret) {
			dev_err(tdev->device.dev,
				"failed to register controller\n");
			dma_async_device_unregister(&tdev->device);
		}
	}

	dev_info(tdev->device.dev, "initialized\n");
	return 0;
}
Exemplo n.º 14
0
static int tas5086_i2c_probe(struct i2c_client *i2c,
			     const struct i2c_device_id *id)
{
	struct tas5086_private *priv;
	struct device *dev = &i2c->dev;
	int gpio_nreset = -EINVAL;
	int i, ret;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	for (i = 0; i < ARRAY_SIZE(supply_names); i++)
		priv->supplies[i].supply = supply_names[i];

	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
				      priv->supplies);
	if (ret < 0) {
		dev_err(dev, "Failed to get regulators: %d\n", ret);
		return ret;
	}

	priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap);
	if (IS_ERR(priv->regmap)) {
		ret = PTR_ERR(priv->regmap);
		dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret);
		return ret;
	}

	i2c_set_clientdata(i2c, priv);

	if (of_match_device(of_match_ptr(tas5086_dt_ids), dev)) {
		struct device_node *of_node = dev->of_node;
		gpio_nreset = of_get_named_gpio(of_node, "reset-gpio", 0);
	}

	if (gpio_is_valid(gpio_nreset))
		if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset"))
			gpio_nreset = -EINVAL;

	priv->gpio_nreset = gpio_nreset;

	ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
	if (ret < 0) {
		dev_err(dev, "Failed to enable regulators: %d\n", ret);
		return ret;
	}

	tas5086_reset(priv);

	/* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */
	ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i);
	if (ret == 0 && i != 0x3) {
		dev_err(dev,
			"Failed to identify TAS5086 codec (got %02x)\n", i);
		ret = -ENODEV;
	}

	/*
	 * The chip has been identified, so we can turn off the power
	 * again until the dai link is set up.
	 */
	regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);

	if (ret == 0)
		ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086,
					     &tas5086_dai, 1);

	return ret;
}
Exemplo n.º 15
0
static int omap_rtc_probe(struct platform_device *pdev)
{
	struct omap_rtc	*rtc;
	struct resource	*res;
	u8 reg, mask, new_ctrl;
	const struct platform_device_id *id_entry;
	const struct of_device_id *of_id;
	int ret;

	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
	if (!rtc)
		return -ENOMEM;

	of_id = of_match_device(omap_rtc_of_match, &pdev->dev);
	if (of_id) {
		rtc->type = of_id->data;
		rtc->is_pmic_controller = rtc->type->has_pmic_mode &&
				of_property_read_bool(pdev->dev.of_node,
						"system-power-controller");
	} else {
		id_entry = platform_get_device_id(pdev);
		rtc->type = (void *)id_entry->driver_data;
	}

	rtc->irq_timer = platform_get_irq(pdev, 0);
	if (rtc->irq_timer <= 0)
		return -ENOENT;

	rtc->irq_alarm = platform_get_irq(pdev, 1);
	if (rtc->irq_alarm <= 0)
		return -ENOENT;

	rtc->clk = devm_clk_get(&pdev->dev, "ext-clk");
	if (!IS_ERR(rtc->clk))
		rtc->has_ext_clk = true;
	else
		rtc->clk = devm_clk_get(&pdev->dev, "int-clk");

	if (!IS_ERR(rtc->clk))
		clk_prepare_enable(rtc->clk);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	rtc->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(rtc->base))
		return PTR_ERR(rtc->base);

	platform_set_drvdata(pdev, rtc);

	/* Enable the clock/module so that we can access the registers */
	pm_runtime_enable(&pdev->dev);
	pm_runtime_get_sync(&pdev->dev);

	rtc->type->unlock(rtc);

	/*
	 * disable interrupts
	 *
	 * NOTE: ALARM2 is not cleared on AM3352 if rtc_write (writeb) is used
	 */
	rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, 0);

	/* enable RTC functional clock */
	if (rtc->type->has_32kclk_en) {
		reg = rtc_read(rtc, OMAP_RTC_OSC_REG);
		rtc_writel(rtc, OMAP_RTC_OSC_REG,
				reg | OMAP_RTC_OSC_32KCLK_EN);
	}

	/* clear old status */
	reg = rtc_read(rtc, OMAP_RTC_STATUS_REG);

	mask = OMAP_RTC_STATUS_ALARM;

	if (rtc->type->has_pmic_mode)
		mask |= OMAP_RTC_STATUS_ALARM2;

	if (rtc->type->has_power_up_reset) {
		mask |= OMAP_RTC_STATUS_POWER_UP;
		if (reg & OMAP_RTC_STATUS_POWER_UP)
			dev_info(&pdev->dev, "RTC power up reset detected\n");
	}

	if (reg & mask)
		rtc_write(rtc, OMAP_RTC_STATUS_REG, reg & mask);

	/* On boards with split power, RTC_ON_NOFF won't reset the RTC */
	reg = rtc_read(rtc, OMAP_RTC_CTRL_REG);
	if (reg & OMAP_RTC_CTRL_STOP)
		dev_info(&pdev->dev, "already running\n");

	/* force to 24 hour mode */
	new_ctrl = reg & (OMAP_RTC_CTRL_SPLIT | OMAP_RTC_CTRL_AUTO_COMP);
	new_ctrl |= OMAP_RTC_CTRL_STOP;

	/*
	 * BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE:
	 *
	 *  - Device wake-up capability setting should come through chip
	 *    init logic. OMAP1 boards should initialize the "wakeup capable"
	 *    flag in the platform device if the board is wired right for
	 *    being woken up by RTC alarm. For OMAP-L138, this capability
	 *    is built into the SoC by the "Deep Sleep" capability.
	 *
	 *  - Boards wired so RTC_ON_nOFF is used as the reset signal,
	 *    rather than nPWRON_RESET, should forcibly enable split
	 *    power mode.  (Some chip errata report that RTC_CTRL_SPLIT
	 *    is write-only, and always reads as zero...)
	 */

	if (new_ctrl & OMAP_RTC_CTRL_SPLIT)
		dev_info(&pdev->dev, "split power mode\n");

	if (reg != new_ctrl)
		rtc_write(rtc, OMAP_RTC_CTRL_REG, new_ctrl);

	/*
	 * If we have the external clock then switch to it so we can keep
	 * ticking across suspend.
	 */
	if (rtc->has_ext_clk) {
		reg = rtc_read(rtc, OMAP_RTC_OSC_REG);
		reg &= ~OMAP_RTC_OSC_OSC32K_GZ_DISABLE;
		reg |= OMAP_RTC_OSC_32KCLK_EN | OMAP_RTC_OSC_SEL_32KCLK_SRC;
		rtc_writel(rtc, OMAP_RTC_OSC_REG, reg);
	}

	rtc->type->lock(rtc);

	device_init_wakeup(&pdev->dev, true);

	rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
			&omap_rtc_ops, THIS_MODULE);
	if (IS_ERR(rtc->rtc)) {
		ret = PTR_ERR(rtc->rtc);
		goto err;
	}

	/* handle periodic and alarm irqs */
	ret = devm_request_irq(&pdev->dev, rtc->irq_timer, rtc_irq, 0,
			dev_name(&rtc->rtc->dev), rtc);
	if (ret)
		goto err;

	if (rtc->irq_timer != rtc->irq_alarm) {
		ret = devm_request_irq(&pdev->dev, rtc->irq_alarm, rtc_irq, 0,
				dev_name(&rtc->rtc->dev), rtc);
		if (ret)
			goto err;
	}

	if (rtc->is_pmic_controller) {
		if (!pm_power_off) {
			omap_rtc_power_off_rtc = rtc;
			pm_power_off = omap_rtc_power_off;
		}
	}

	/* Support ext_wakeup pinconf */
	rtc_pinctrl_desc.name = dev_name(&pdev->dev);

	rtc->pctldev = pinctrl_register(&rtc_pinctrl_desc, &pdev->dev, rtc);
	if (IS_ERR(rtc->pctldev)) {
		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
		return PTR_ERR(rtc->pctldev);
	}

	return 0;

err:
	device_init_wakeup(&pdev->dev, false);
	rtc->type->lock(rtc);
	pm_runtime_put_sync(&pdev->dev);
	pm_runtime_disable(&pdev->dev);

	return ret;
}
Exemplo n.º 16
0
Arquivo: ahb.c Projeto: Anjali05/linux
static int ath10k_ahb_probe(struct platform_device *pdev)
{
	struct ath10k *ar;
	struct ath10k_ahb *ar_ahb;
	struct ath10k_pci *ar_pci;
	const struct of_device_id *of_id;
	enum ath10k_hw_rev hw_rev;
	size_t size;
	int ret;
	struct ath10k_bus_params bus_params;

	of_id = of_match_device(ath10k_ahb_of_match, &pdev->dev);
	if (!of_id) {
		dev_err(&pdev->dev, "failed to find matching device tree id\n");
		return -EINVAL;
	}

	hw_rev = (enum ath10k_hw_rev)of_id->data;

	size = sizeof(*ar_pci) + sizeof(*ar_ahb);
	ar = ath10k_core_create(size, &pdev->dev, ATH10K_BUS_AHB,
				hw_rev, &ath10k_ahb_hif_ops);
	if (!ar) {
		dev_err(&pdev->dev, "failed to allocate core\n");
		return -ENOMEM;
	}

	ath10k_dbg(ar, ATH10K_DBG_BOOT, "ahb probe\n");

	ar_pci = ath10k_pci_priv(ar);
	ar_ahb = ath10k_ahb_priv(ar);

	ar_ahb->pdev = pdev;
	platform_set_drvdata(pdev, ar);

	ret = ath10k_ahb_resource_init(ar);
	if (ret)
		goto err_core_destroy;

	ar->dev_id = 0;
	ar_pci->mem = ar_ahb->mem;
	ar_pci->mem_len = ar_ahb->mem_len;
	ar_pci->ar = ar;
	ar_pci->ce.bus_ops = &ath10k_ahb_bus_ops;
	ar_pci->targ_cpu_to_ce_addr = ath10k_ahb_qca4019_targ_cpu_to_ce_addr;
	ar->ce_priv = &ar_pci->ce;

	ret = ath10k_pci_setup_resource(ar);
	if (ret) {
		ath10k_err(ar, "failed to setup resource: %d\n", ret);
		goto err_resource_deinit;
	}

	ath10k_pci_init_napi(ar);

	ret = ath10k_ahb_request_irq_legacy(ar);
	if (ret)
		goto err_free_pipes;

	ret = ath10k_ahb_prepare_device(ar);
	if (ret)
		goto err_free_irq;

	ath10k_pci_ce_deinit(ar);

	bus_params.dev_type = ATH10K_DEV_TYPE_LL;
	bus_params.chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
	if (bus_params.chip_id == 0xffffffff) {
		ath10k_err(ar, "failed to get chip id\n");
		ret = -ENODEV;
		goto err_halt_device;
	}

	ret = ath10k_core_register(ar, &bus_params);
	if (ret) {
		ath10k_err(ar, "failed to register driver core: %d\n", ret);
		goto err_halt_device;
	}

	return 0;

err_halt_device:
	ath10k_ahb_halt_chip(ar);
	ath10k_ahb_clock_disable(ar);

err_free_irq:
	ath10k_ahb_release_irq_legacy(ar);

err_free_pipes:
	ath10k_pci_free_pipes(ar);

err_resource_deinit:
	ath10k_ahb_resource_deinit(ar);

err_core_destroy:
	ath10k_core_destroy(ar);
	platform_set_drvdata(pdev, NULL);

	return ret;
}
Exemplo n.º 17
0
Arquivo: dev.c Projeto: 03199618/linux
static int host1x_probe(struct platform_device *pdev)
{
	const struct of_device_id *id;
	struct host1x *host;
	struct resource *regs;
	int syncpt_irq;
	int err;

	id = of_match_device(host1x_of_match, &pdev->dev);
	if (!id)
		return -EINVAL;

	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!regs) {
		dev_err(&pdev->dev, "failed to get registers\n");
		return -ENXIO;
	}

	syncpt_irq = platform_get_irq(pdev, 0);
	if (syncpt_irq < 0) {
		dev_err(&pdev->dev, "failed to get IRQ\n");
		return -ENXIO;
	}

	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
	if (!host)
		return -ENOMEM;

	host->dev = &pdev->dev;
	host->info = id->data;

	/* set common host1x device data */
	platform_set_drvdata(pdev, host);

	host->regs = devm_ioremap_resource(&pdev->dev, regs);
	if (IS_ERR(host->regs))
		return PTR_ERR(host->regs);

	if (host->info->init) {
		err = host->info->init(host);
		if (err)
			return err;
	}

	host->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(host->clk)) {
		dev_err(&pdev->dev, "failed to get clock\n");
		err = PTR_ERR(host->clk);
		return err;
	}

	err = host1x_channel_list_init(host);
	if (err) {
		dev_err(&pdev->dev, "failed to initialize channel list\n");
		return err;
	}

	err = clk_prepare_enable(host->clk);
	if (err < 0) {
		dev_err(&pdev->dev, "failed to enable clock\n");
		return err;
	}

	err = host1x_syncpt_init(host);
	if (err) {
		dev_err(&pdev->dev, "failed to initialize syncpts\n");
		return err;
	}

	err = host1x_intr_init(host, syncpt_irq);
	if (err) {
		dev_err(&pdev->dev, "failed to initialize interrupts\n");
		goto fail_deinit_syncpt;
	}

	host1x_debug_init(host);

	host1x_drm_alloc(pdev);

	return 0;

fail_deinit_syncpt:
	host1x_syncpt_deinit(host);
	return err;
}
Exemplo n.º 18
0
static int __devinit msm_serial_hsl_probe_irda(struct platform_device *pdev)
{
	struct msm_hsl_port *msm_hsl_port;
	struct resource *uart_resource;
	struct resource *gsbi_resource;
	struct uart_port *port;
	const struct of_device_id *match;
	struct irda_platform_data *pdata;
	int ret;

	if (pdev->id == -1)
		pdev->id = atomic_inc_return(&msm_serial_hsl_next_id) - 1;

	if (unlikely(pdev->id < 0 || pdev->id >= UART_NR))
		return -ENXIO;

	printk(KERN_INFO "msm_serial_irda: detected port #%d\n", pdev->id);

	port = get_port_from_line(pdev->id);
	port->dev = &pdev->dev;
	pdata = pdev->dev.platform_data;
	if (!pdata) {
		E("[irdaerror]%s: Assign platform_data error!!\n",
			__func__);
		return -ENXIO;
	}
	msm_hsl_port = UART_TO_MSM(port);
	msm_hsl_port->irda_enable= pdata->irda_enable;
	htc_irda_port = msm_hsl_port;

	match = of_match_device(msm_hsl_match_table, &pdev->dev);
	if (!match)
		msm_hsl_port->ver_id = UARTDM_VERSION_11_13;
	else {
		D("%s () match:port->line %d, ir\n", __func__, port->line);
		msm_hsl_port->ver_id = (unsigned int)match->data;
	}

	gsbi_resource =	platform_get_resource_byname(pdev,
						     IORESOURCE_MEM,
						     "gsbi_resource");
	if (!gsbi_resource) {
		gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
		D("%s () gsbi_resourc:port->line %d, ir\n", __func__, port->line);
	}
	msm_hsl_port->clk = clk_get(&pdev->dev, "core_clk");
	if (gsbi_resource) {
printk(KERN_INFO "msm_serial_irda: get gsbi_uart_clk and gsbi_pclk\n");
		msm_hsl_port->is_uartdm = 1;
		msm_hsl_port->pclk = clk_get(&pdev->dev, "iface_clk");
	} else {
printk(KERN_INFO "msm_serial_irda: get uartdm_clk\n");
		msm_hsl_port->is_uartdm = 0;
		msm_hsl_port->pclk = NULL;
	}

	if (unlikely(IS_ERR(msm_hsl_port->clk))) {
		printk(KERN_ERR "%s: Error getting clk\n", __func__);
		return PTR_ERR(msm_hsl_port->clk);
	}
	if (unlikely(IS_ERR(msm_hsl_port->pclk))) {
		printk(KERN_ERR "%s: Error getting pclk\n", __func__);
		return PTR_ERR(msm_hsl_port->pclk);
	}

	uart_resource = platform_get_resource_byname(pdev,
						     IORESOURCE_MEM,
						     "uartdm_resource");
	if (!uart_resource)
		uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (unlikely(!uart_resource)) {
		printk(KERN_ERR "getting uartdm_resource failed\n");
		return -ENXIO;
	}
	port->mapbase = uart_resource->start;
printk(KERN_INFO "msm_serial_hsl: port[%d] mapbase:%x\n", port->line, port->mapbase);

	port->irq = platform_get_irq(pdev, 0);
	if (unlikely((int)port->irq < 0)) {
		printk(KERN_ERR "%s: getting irq failed\n", __func__);
		return -ENXIO;
	}

	device_set_wakeup_capable(&pdev->dev, 1);
	platform_set_drvdata(pdev, port);
	pm_runtime_enable(port->dev);
#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
	ret = device_create_file(&pdev->dev, &dev_attr_console);
	D("%s () device_create_file, port->line %d, ir\n", __func__, port->line);
	if (unlikely(ret))
		E("%s():Can't create console attribute\n", __func__);
#endif
	msm_hsl_debugfs_init(msm_hsl_port, pdev->id);

	/* Temporarily increase the refcount on the GSBI clock to avoid a race
	 * condition with the earlyprintk handover mechanism.
	 */
	if (msm_hsl_port->pclk) {
		clk_prepare_enable(msm_hsl_port->pclk);
		D("%s () clk_enable, port->line %d, ir\n", __func__, port->line);
	}
	ret = uart_add_one_port(&msm_hsl_uart_driver, port);
	if (msm_hsl_port->pclk) {
		D("%s () clk_disabl, port->line %d, ir\n", __func__, port->line);
		clk_disable_unprepare(msm_hsl_port->pclk);
	}

	D("%s ():port->line %d, ir\n", __func__, port->line);
		msm_hsl_port->irda_class = class_create(THIS_MODULE, "htc_irda");
	if (IS_ERR(msm_hsl_port->irda_class)) {
		ret = PTR_ERR(msm_hsl_port->irda_class);
		msm_hsl_port->irda_class = NULL;
		return -ENXIO;
	}
	msm_hsl_port->irda_dev = device_create(msm_hsl_port->irda_class,
				NULL, 0, "%s", "irda");
	if (unlikely(IS_ERR(msm_hsl_port->irda_dev))) {
		ret = PTR_ERR(msm_hsl_port->irda_dev);
		msm_hsl_port->irda_dev = NULL;
		goto err_create_ls_device;
	}
		/* register the attributes */
	ret = device_create_file(msm_hsl_port->irda_dev, &dev_attr_enable_irda);
	if (ret)
		goto err_create_ls_device_file;

	msm_hsl_write(port, 3, UARTDM_IRDA_ADDR);
	enable_irda(0);/*0 disable, 3=enable, 9=loopback*/
	return ret;

err_create_ls_device_file:
	device_unregister(msm_hsl_port->irda_dev);
err_create_ls_device:
	class_destroy(msm_hsl_port->irda_class);
	return ret;
	return ret;
}
Exemplo n.º 19
0
static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
{
	const struct of_device_id *match;
	struct of_serial_info *info;
	struct uart_port port;
	int port_type;
	int ret;
	int ids;

	match = of_match_device(of_platform_serial_table, &ofdev->dev);
	if (!match)
		return -EINVAL;

	if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
		return -EBUSY;

	info = kmalloc(sizeof(*info), GFP_KERNEL);
	if (info == NULL)
		return -ENOMEM;

	port_type = (unsigned long)match->data;
	ret = of_platform_serial_setup(ofdev, port_type, &port);
	if (ret)
		goto out;

	ids = of_alias_get_id(ofdev->dev.of_node, "serial");
	if (ids < 0) {
		dev_warn(&ofdev->dev, "FAILED to find out alias id\n");
	} else {
		if (ids < CONFIG_SERIAL_8250_RUNTIME_UARTS)
			port.line = ids;
		else {
			dev_warn(&ofdev->dev,
				"FAILED to register serial driver with id %d\n",
									ids);
			goto out;
		}
	}

	switch (port_type) {
#ifdef CONFIG_SERIAL_8250
	case PORT_8250 ... PORT_MAX_8250:
		ret = serial8250_register_port(&port);
		break;
#endif
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
	case PORT_NWPSERIAL:
		ret = nwpserial_register_port(&port);
		break;
#endif
	default:
		/* need to add code for these */
	case PORT_UNKNOWN:
		dev_info(&ofdev->dev, "Unknown serial port found, ignored\n");
		ret = -ENODEV;
		break;
	}
	if (ret < 0)
		goto out;

	info->type = port_type;
	info->line = ret;
	dev_set_drvdata(&ofdev->dev, info);
	return 0;
out:
	kfree(info);
	irq_dispose_mapping(port.irq);
	return ret;
}
Exemplo n.º 20
0
static int bcm2835_thermal_probe(struct platform_device *pdev)
{
	const struct of_device_id *match;
	struct thermal_zone_device *tz;
	struct bcm2835_thermal_data *data;
	struct resource *res;
	int err = 0;
	u32 val;
	unsigned long rate;

	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	match = of_match_device(bcm2835_thermal_of_match_table,
				&pdev->dev);
	if (!match)
		return -EINVAL;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	data->regs = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(data->regs)) {
		err = PTR_ERR(data->regs);
		dev_err(&pdev->dev, "Could not get registers: %d\n", err);
		return err;
	}

	data->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(data->clk)) {
		err = PTR_ERR(data->clk);
		if (err != -EPROBE_DEFER)
			dev_err(&pdev->dev, "Could not get clk: %d\n", err);
		return err;
	}

	err = clk_prepare_enable(data->clk);
	if (err)
		return err;

	rate = clk_get_rate(data->clk);
	if ((rate < 1920000) || (rate > 5000000))
		dev_warn(&pdev->dev,
			 "Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz\n",
			 data->clk, data->clk);

	/* register of thermal sensor and get info from DT */
	tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
					     &bcm2835_thermal_ops);
	if (IS_ERR(tz)) {
		err = PTR_ERR(tz);
		dev_err(&pdev->dev,
			"Failed to register the thermal device: %d\n",
			err);
		goto err_clk;
	}

	/*
	 * right now the FW does set up the HW-block, so we are not
	 * touching the configuration registers.
	 * But if the HW is not enabled, then set it up
	 * using "sane" values used by the firmware right now.
	 */
	val = readl(data->regs + BCM2835_TS_TSENSCTL);
	if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {
		int trip_temp, offset, slope;

		slope = thermal_zone_get_slope(tz);
		offset = thermal_zone_get_offset(tz);
		/*
		 * For now we deal only with critical, otherwise
		 * would need to iterate
		 */
		err = tz->ops->get_trip_temp(tz, 0, &trip_temp);
		if (err < 0) {
			dev_err(&pdev->dev,
				"Not able to read trip_temp: %d\n",
				err);
			goto err_tz;
		}

		/* set bandgap reference voltage and enable voltage regulator */
		val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT <<
		       BCM2835_TS_TSENSCTL_CTRL_SHIFT) |
		      BCM2835_TS_TSENSCTL_REGULEN;

		/* use the recommended reset duration */
		val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);

		/*  trip_adc value from info */
		val |= bcm2835_thermal_temp2adc(trip_temp,
						offset,
						slope)
			<< BCM2835_TS_TSENSCTL_THOLD_SHIFT;

		/* write the value back to the register as 2 steps */
		writel(val, data->regs + BCM2835_TS_TSENSCTL);
		val |= BCM2835_TS_TSENSCTL_RSTB;
		writel(val, data->regs + BCM2835_TS_TSENSCTL);
	}

	data->tz = tz;

	platform_set_drvdata(pdev, tz);

	bcm2835_thermal_debugfs(pdev);

	return 0;
err_tz:
	thermal_zone_of_sensor_unregister(&pdev->dev, tz);
err_clk:
	clk_disable_unprepare(data->clk);

	return err;
}
static int tegra30_ahub_probe(struct platform_device *pdev)
{
	const struct of_device_id *match;
	const struct tegra30_ahub_soc_data *soc_data;
	struct clk *clk;
	int i;
	struct resource *res0, *res1, *region;
	u32 of_dma[2];
	void __iomem *regs_apbif, *regs_ahub;
	int ret = 0;

	if (ahub)
		return -ENODEV;

	match = of_match_device(tegra30_ahub_of_match, &pdev->dev);
	if (!match)
		return -EINVAL;
	soc_data = match->data;

	/*
	 * The AHUB hosts a register bus: the "configlink". For this to
	 * operate correctly, all devices on this bus must be out of reset.
	 * Ensure that here.
	 */
	for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) {
		if (!(configlink_clocks[i].clk_list_mask &
					soc_data->clk_list_mask))
			continue;
		clk = clk_get(&pdev->dev, configlink_clocks[i].clk_name);
		if (IS_ERR(clk)) {
			dev_err(&pdev->dev, "Can't get clock %s\n",
				configlink_clocks[i].clk_name);
			ret = PTR_ERR(clk);
			goto err;
		}
		tegra_periph_reset_deassert(clk);
		clk_put(clk);
	}

	ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub),
			    GFP_KERNEL);
	if (!ahub) {
		dev_err(&pdev->dev, "Can't allocate tegra30_ahub\n");
		ret = -ENOMEM;
		goto err;
	}
	dev_set_drvdata(&pdev->dev, ahub);

	ahub->dev = &pdev->dev;

	ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio");
	if (IS_ERR(ahub->clk_d_audio)) {
		dev_err(&pdev->dev, "Can't retrieve ahub d_audio clock\n");
		ret = PTR_ERR(ahub->clk_d_audio);
		goto err;
	}

	ahub->clk_apbif = clk_get(&pdev->dev, "apbif");
	if (IS_ERR(ahub->clk_apbif)) {
		dev_err(&pdev->dev, "Can't retrieve ahub apbif clock\n");
		ret = PTR_ERR(ahub->clk_apbif);
		goto err_clk_put_d_audio;
	}

	if (of_property_read_u32_array(pdev->dev.of_node,
				"nvidia,dma-request-selector",
				of_dma, 2) < 0) {
		dev_err(&pdev->dev,
			"Missing property nvidia,dma-request-selector\n");
		ret = -ENODEV;
		goto err_clk_put_d_audio;
	}
	ahub->dma_sel = of_dma[1];

	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res0) {
		dev_err(&pdev->dev, "No apbif memory resource\n");
		ret = -ENODEV;
		goto err_clk_put_apbif;
	}

	region = devm_request_mem_region(&pdev->dev, res0->start,
					 resource_size(res0), DRV_NAME);
	if (!region) {
		dev_err(&pdev->dev, "request region apbif failed\n");
		ret = -EBUSY;
		goto err_clk_put_apbif;
	}
	ahub->apbif_addr = res0->start;

	regs_apbif = devm_ioremap(&pdev->dev, res0->start,
				  resource_size(res0));
	if (!regs_apbif) {
		dev_err(&pdev->dev, "ioremap apbif failed\n");
		ret = -ENOMEM;
		goto err_clk_put_apbif;
	}

	ahub->regmap_apbif = devm_regmap_init_mmio(&pdev->dev, regs_apbif,
					&tegra30_ahub_apbif_regmap_config);
	if (IS_ERR(ahub->regmap_apbif)) {
		dev_err(&pdev->dev, "apbif regmap init failed\n");
		ret = PTR_ERR(ahub->regmap_apbif);
		goto err_clk_put_apbif;
	}
	regcache_cache_only(ahub->regmap_apbif, true);

	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (!res1) {
		dev_err(&pdev->dev, "No ahub memory resource\n");
		ret = -ENODEV;
		goto err_clk_put_apbif;
	}

	region = devm_request_mem_region(&pdev->dev, res1->start,
					 resource_size(res1), DRV_NAME);
	if (!region) {
		dev_err(&pdev->dev, "request region ahub failed\n");
		ret = -EBUSY;
		goto err_clk_put_apbif;
	}

	regs_ahub = devm_ioremap(&pdev->dev, res1->start,
				 resource_size(res1));
	if (!regs_ahub) {
		dev_err(&pdev->dev, "ioremap ahub failed\n");
		ret = -ENOMEM;
		goto err_clk_put_apbif;
	}

	ahub->regmap_ahub = devm_regmap_init_mmio(&pdev->dev, regs_ahub,
					&tegra30_ahub_ahub_regmap_config);
	if (IS_ERR(ahub->regmap_ahub)) {
		dev_err(&pdev->dev, "ahub regmap init failed\n");
		ret = PTR_ERR(ahub->regmap_ahub);
		goto err_clk_put_apbif;
	}
	regcache_cache_only(ahub->regmap_ahub, true);

	pm_runtime_enable(&pdev->dev);
	if (!pm_runtime_enabled(&pdev->dev)) {
		ret = tegra30_ahub_runtime_resume(&pdev->dev);
		if (ret)
			goto err_pm_disable;
	}

	of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);

	return 0;

err_pm_disable:
	pm_runtime_disable(&pdev->dev);
err_clk_put_apbif:
	clk_put(ahub->clk_apbif);
err_clk_put_d_audio:
	clk_put(ahub->clk_d_audio);
	ahub = NULL;
err:
	return ret;
}
Exemplo n.º 22
0
static int __devinit twlreg_probe(struct platform_device *pdev)
{
	int				i, id;
	struct twlreg_info		*info;
	struct regulator_init_data	*initdata;
	struct regulation_constraints	*c;
	struct regulator_dev		*rdev;
	struct twl_regulator_driver_data	*drvdata;
	const struct of_device_id	*match;
	u32 twl_errata = 0;

	match = of_match_device(twl_of_match, &pdev->dev);
	if (match) {
		info = match->data;
		id = info->desc.id;
		initdata = of_get_regulator_init_data(&pdev->dev,
						      pdev->dev.of_node);
		drvdata = NULL;
	} else {
		id = pdev->id;
		initdata = pdev->dev.platform_data;
		for (i = 0, info = NULL; i < ARRAY_SIZE(twl_of_match); i++) {
			info = twl_of_match[i].data;
			if (!info || info->desc.id != id)
				continue;
			break;
		}
		drvdata = initdata->driver_data;
		if (!drvdata)
			return -EINVAL;
	}

	if (!info)
		return -ENODEV;

	if (!initdata)
		return -EINVAL;

	if (drvdata) {
		/* copy the driver data into regulator data */
		info->features = drvdata->features;
		twl_errata = drvdata->errata;
		info->data = drvdata->data;
		info->set_voltage = drvdata->set_voltage;
		info->get_voltage = drvdata->get_voltage;
	}

	/* Constrain board-specific capabilities according to what
	 * this driver and the chip itself can actually do.
	 */
	c = &initdata->constraints;
	c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY;
	c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE
				| REGULATOR_CHANGE_MODE
				| REGULATOR_CHANGE_STATUS;
	switch (id) {
	case TWL4030_REG_VIO:
	case TWL4030_REG_VDD1:
	case TWL4030_REG_VDD2:
	case TWL4030_REG_VPLL1:
	case TWL4030_REG_VINTANA1:
	case TWL4030_REG_VINTANA2:
	case TWL4030_REG_VINTDIG:
		c->always_on = true;
		break;
	default:
		break;
	}

	switch (id) {
	case TWL6032_REG_SMPS3:
		if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3)
			info->flags |= SMPS_EXTENDED_EN;
		if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3)
			info->flags |= SMPS_OFFSET_EN;
		break;
	case TWL6032_REG_SMPS4:
		if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4)
			info->flags |= SMPS_EXTENDED_EN;
		if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4)
			info->flags |= SMPS_OFFSET_EN;
		break;
	case TWL6032_REG_VIO:
		if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO)
			info->flags |= SMPS_EXTENDED_EN;
		if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO)
			info->flags |= SMPS_OFFSET_EN;
		break;
	case TWL6030_REG_SYSEN:
	case TWL6032_REG_LDO6:
	case TWL6032_REG_LDOLN:
		if (twl_errata & TWL6032_ERRATA_LDO_MUST_BE_ALWAYS_ON) {
			c->state_mem.enabled = true;
			c->state_mem.disabled = false;
		}
		break;
	}

	rdev = regulator_register(&info->desc, &pdev->dev, initdata, info,
							pdev->dev.of_node);
	if (IS_ERR(rdev)) {
		dev_err(&pdev->dev, "can't register %s, %ld\n",
				info->desc.name, PTR_ERR(rdev));
		return PTR_ERR(rdev);
	}
	platform_set_drvdata(pdev, rdev);

	if (twl_class_is_4030())
		twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_REMAP,
						info->remap);

	/* NOTE:  many regulators support short-circuit IRQs (presentable
	 * as REGULATOR_OVER_CURRENT notifications?) configured via:
	 *  - SC_CONFIG
	 *  - SC_DETECT1 (vintana2, vmmc1/2, vaux1/2/3/4)
	 *  - SC_DETECT2 (vusb, vdac, vio, vdd1/2, vpll2)
	 *  - IT_CONFIG
	 */

	return 0;
}
Exemplo n.º 23
0
static int omap_usb2_probe(struct platform_device *pdev)
{
	struct omap_usb	*phy;
	struct phy *generic_phy;
	struct resource *res;
	struct phy_provider *phy_provider;
	struct usb_otg *otg;
	struct device_node *node = pdev->dev.of_node;
	struct device_node *control_node;
	struct platform_device *control_pdev;
	const struct of_device_id *of_id;
	struct usb_phy_data *phy_data;

	of_id = of_match_device(omap_usb2_id_table, &pdev->dev);

	if (!of_id)
		return -EINVAL;

	phy_data = (struct usb_phy_data *)of_id->data;

	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
	if (!phy)
		return -ENOMEM;

	otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
	if (!otg)
		return -ENOMEM;

	phy->dev		= &pdev->dev;

	phy->phy.dev		= phy->dev;
	phy->phy.label		= phy_data->label;
	phy->phy.otg		= otg;
	phy->phy.type		= USB_PHY_TYPE_USB2;
	phy->mask		= phy_data->mask;
	phy->power_on		= phy_data->power_on;
	phy->power_off		= phy_data->power_off;

	if (phy_data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
		phy->phy_base = devm_ioremap_resource(&pdev->dev, res);
		if (IS_ERR(phy->phy_base))
			return PTR_ERR(phy->phy_base);
		phy->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT;
	}

	phy->syscon_phy_power = syscon_regmap_lookup_by_phandle(node,
							"syscon-phy-power");
	if (IS_ERR(phy->syscon_phy_power)) {
		dev_dbg(&pdev->dev,
			"can't get syscon-phy-power, using control device\n");
		phy->syscon_phy_power = NULL;

		control_node = of_parse_phandle(node, "ctrl-module", 0);
		if (!control_node) {
			dev_err(&pdev->dev,
				"Failed to get control device phandle\n");
			return -EINVAL;
		}

		control_pdev = of_find_device_by_node(control_node);
		if (!control_pdev) {
			dev_err(&pdev->dev, "Failed to get control device\n");
			return -EINVAL;
		}
		phy->control_dev = &control_pdev->dev;
	} else {
		if (of_property_read_u32_index(node,
					       "syscon-phy-power", 1,
					       &phy->power_reg)) {
			dev_err(&pdev->dev,
				"couldn't get power reg. offset\n");
			return -EINVAL;
		}
	}


	phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
	if (IS_ERR(phy->wkupclk)) {
		if (PTR_ERR(phy->wkupclk) == -EPROBE_DEFER)
			return -EPROBE_DEFER;

		dev_warn(&pdev->dev, "unable to get wkupclk %ld, trying old name\n",
			 PTR_ERR(phy->wkupclk));
		phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");

		if (IS_ERR(phy->wkupclk)) {
			if (PTR_ERR(phy->wkupclk) != -EPROBE_DEFER)
				dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
			return PTR_ERR(phy->wkupclk);
		} else {
			dev_warn(&pdev->dev,
				 "found usb_phy_cm_clk32k, please fix DTS\n");
		}
	}

	phy->optclk = devm_clk_get(phy->dev, "refclk");
	if (IS_ERR(phy->optclk)) {
		if (PTR_ERR(phy->optclk) == -EPROBE_DEFER)
			return -EPROBE_DEFER;

		dev_dbg(&pdev->dev, "unable to get refclk, trying old name\n");
		phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");

		if (IS_ERR(phy->optclk)) {
			if (PTR_ERR(phy->optclk) != -EPROBE_DEFER) {
				dev_dbg(&pdev->dev,
					"unable to get usb_otg_ss_refclk960m\n");
			}
		} else {
			dev_warn(&pdev->dev,
				 "found usb_otg_ss_refclk960m, please fix DTS\n");
		}
	}

	otg->set_host = omap_usb_set_host;
	otg->set_peripheral = omap_usb_set_peripheral;
	if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS)
		otg->set_vbus = omap_usb_set_vbus;
	if (phy_data->flags & OMAP_USB2_HAS_START_SRP)
		otg->start_srp = omap_usb_start_srp;
	otg->usb_phy = &phy->phy;

	platform_set_drvdata(pdev, phy);
	pm_runtime_enable(phy->dev);

	generic_phy = devm_phy_create(phy->dev, NULL, &ops);
	if (IS_ERR(generic_phy)) {
		pm_runtime_disable(phy->dev);
		return PTR_ERR(generic_phy);
	}

	phy_set_drvdata(generic_phy, phy);
	omap_usb_power_off(generic_phy);

	phy_provider = devm_of_phy_provider_register(phy->dev,
						     of_phy_simple_xlate);
	if (IS_ERR(phy_provider)) {
		pm_runtime_disable(phy->dev);
		return PTR_ERR(phy_provider);
	}


	usb_add_phy_dev(&phy->phy);

	return 0;
}
Exemplo n.º 24
0
static int fs_enet_mdio_probe(struct platform_device *ofdev)
{
	const struct of_device_id *match;
	struct resource res;
	struct mii_bus *new_bus;
	struct fec_info *fec;
	int (*get_bus_freq)(struct device_node *);
	int ret = -ENOMEM, clock, speed;

	match = of_match_device(fs_enet_mdio_fec_match, &ofdev->dev);
	if (!match)
		return -EINVAL;
	get_bus_freq = match->data;

	new_bus = mdiobus_alloc();
	if (!new_bus)
		goto out;

	fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
	if (!fec)
		goto out_mii;

	new_bus->priv = fec;
	new_bus->name = "FEC MII Bus";
	new_bus->read = &fs_enet_fec_mii_read;
	new_bus->write = &fs_enet_fec_mii_write;

	ret = of_address_to_resource(ofdev->dev.of_node, 0, &res);
	if (ret)
		goto out_res;

	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);

	fec->fecp = ioremap(res.start, resource_size(&res));
	if (!fec->fecp) {
		ret = -ENOMEM;
		goto out_fec;
	}

	if (get_bus_freq) {
		clock = get_bus_freq(ofdev->dev.of_node);
		if (!clock) {
			/* Use maximum divider if clock is unknown */
			dev_warn(&ofdev->dev, "could not determine IPS clock\n");
			clock = 0x3F * 5000000;
		}
	} else
		clock = ppc_proc_freq;

	/*
	 * Scale for a MII clock <= 2.5 MHz
	 * Note that only 6 bits (25:30) are available for MII speed.
	 */
	speed = (clock + 4999999) / 5000000;
	if (speed > 0x3F) {
		speed = 0x3F;
		dev_err(&ofdev->dev,
			"MII clock (%d Hz) exceeds max (2.5 MHz)\n",
			clock / speed);
	}

	fec->mii_speed = speed << 1;

	setbits32(&fec->fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
	setbits32(&fec->fecp->fec_ecntrl, FEC_ECNTRL_PINMUX |
	                                  FEC_ECNTRL_ETHER_EN);
	out_be32(&fec->fecp->fec_ievent, FEC_ENET_MII);
	clrsetbits_be32(&fec->fecp->fec_mii_speed, 0x7E, fec->mii_speed);

	new_bus->phy_mask = ~0;

	new_bus->parent = &ofdev->dev;
	platform_set_drvdata(ofdev, new_bus);

	ret = of_mdiobus_register(new_bus, ofdev->dev.of_node);
	if (ret)
		goto out_unmap_regs;

	return 0;

out_unmap_regs:
	iounmap(fec->fecp);
out_res:
out_fec:
	kfree(fec);
out_mii:
	mdiobus_free(new_bus);
out:
	return ret;
}
static int hi6402_mbhc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct hi6402_mbhc_platform_data *pdata = NULL;
	const struct of_device_id *match = NULL;
	int ret = 0;

	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
	if (NULL == pdata) {
		dev_err(dev, "cannot allocate hisi 6421 spk platform data\n");
		return -ENOMEM;
	}

	match = of_match_device(hi6402_mbhc_of_match, dev);
	if (!match) {
		pr_err("get device info err\n");
		return -ENOENT;
	} else {
		struct device_node *node = dev->of_node;
		int temp;

		/* get board defination */
		if (!of_property_read_u32(node, "hisilicon,hi6402_hs_det_inv", &temp))
			pdata->hs_det_inv = temp;
		else
			pdata->hs_det_inv = 0;

		if (!of_property_read_u32(node, "hisilicon,hs_3_pole_min_voltage", &temp))
			pdata->hs_3_pole_min_voltage = temp;
		else
			pdata->hs_3_pole_min_voltage = 0;

		if (!of_property_read_u32(node, "hisilicon,hs_3_pole_max_voltage", &temp))
			pdata->hs_3_pole_max_voltage = temp;
		else
			pdata->hs_3_pole_max_voltage = 0;

		if (!of_property_read_u32(node, "hisilicon,hs_4_pole_min_voltage", &temp))
			pdata->hs_4_pole_min_voltage = temp;
		else
			pdata->hs_4_pole_min_voltage = 0;

		if (!of_property_read_u32(node, "hisilicon,hs_4_pole_max_voltage", &temp))
			pdata->hs_4_pole_max_voltage = temp;
		else
			pdata->hs_4_pole_max_voltage = 0;

		if (!of_property_read_u32(node, "hisilicon,btn_play_min_voltage", &temp))
			pdata->btn_play_min_voltage = temp;
		else
			pdata->btn_play_min_voltage = 0;

		if (!of_property_read_u32(node, "hisilicon,btn_play_max_voltage", &temp))
			pdata->btn_play_max_voltage = temp;
		else
			pdata->btn_play_max_voltage = 0;

		if (!of_property_read_u32(node, "hisilicon,btn_volume_up_min_voltage", &temp))
			pdata->btn_volume_up_min_voltage = temp;
		else
			pdata->btn_volume_up_min_voltage = 0;

		if (!of_property_read_u32(node, "hisilicon,btn_volume_up_max_voltage", &temp))
			pdata->btn_volume_up_max_voltage = temp;
		else
			pdata->btn_volume_up_max_voltage = 0;

		if (!of_property_read_u32(node, "hisilicon,btn_volume_down_min_voltage", &temp))
			pdata->btn_volume_down_min_voltage = temp;
		else
			pdata->btn_volume_down_min_voltage = 0;

		if (!of_property_read_u32(node, "hisilicon,btn_volume_down_max_voltage", &temp))
			pdata->btn_volume_down_max_voltage = temp;
		else
			pdata->btn_volume_down_max_voltage = 0;
	}

	pdata->p_irq = dev_get_drvdata(pdev->dev.parent);
	if (!pdata->p_irq) {
		dev_err(dev, "get parend device error\n");
		return -ENOENT;
	}

#ifdef CONFIG_SWITCH
	pdata->sdev.name = "h2w";
	ret = switch_dev_register(&pdata->sdev);
	if (ret) {
		pr_err("%s : error registering switch device %d\n", __FUNCTION__, ret);
		return ret;
	}
#endif

	/* get irqs */
	pdata->irq[HI6402_IRQ_PLL_UNLOCK] = platform_get_irq_byname(pdev, "pll_unlock");
	if (0 > pdata->irq[HI6402_IRQ_PLL_UNLOCK]) {
		pr_err("get pll unlock error");
		return -ENOENT;
	}

	pdata->irq[HI6402_IRQ_SOUND_TRIGER] = platform_get_irq_byname(pdev, "sound_triger");
	if (0 > pdata->irq[HI6402_IRQ_SOUND_TRIGER]) {
		pr_err("get sound triger error");
		return -ENOENT;
	}

	pdata->irq[HI6402_IRQ_PLUGOUT] = platform_get_irq_byname(pdev, "plugout");
	if (0 > pdata->irq[HI6402_IRQ_PLUGOUT]) {
		pr_err("get plug out irq num error");
		return -ENOENT;
	}

	pdata->irq[HI6402_IRQ_PLUGIN] = platform_get_irq_byname(pdev, "plugin");
	if (0 > pdata->irq[HI6402_IRQ_PLUGIN]) {
		pr_err("get plug in irq num error");
		return -ENOENT;
	}

	pdata->irq[HI6402_IRQ_BTNDOWN_ECO] = platform_get_irq_byname(pdev, "btndown_eco");
	if (0 > pdata->irq[HI6402_IRQ_BTNDOWN_ECO]) {
		pr_err("get btn down eco irq num error");
		return -ENOENT;
	}

	pdata->irq[HI6402_IRQ_BTNUP_ECO] = platform_get_irq_byname(pdev, "btnup_eco");
	if (0 > pdata->irq[HI6402_IRQ_BTNUP_ECO]) {
		pr_err("get btn up eco irq num error");
		return -ENOENT;
	}

	pdata->irq[HI6402_IRQ_BTNDOWN_COMP1] = platform_get_irq_byname(pdev, "btndown");
	if (0 > pdata->irq[HI6402_IRQ_BTNDOWN_COMP1]) {
		pr_err("get btn down irq num error");
		return -ENOENT;
	}

	pdata->irq[HI6402_IRQ_BTNUP_COMP1] = platform_get_irq_byname(pdev, "btnup");
	if (0 > pdata->irq[HI6402_IRQ_BTNUP_COMP1]) {
		pr_err("get btn up irq num error");
		return -ENOENT;
	}

	wake_lock_init(&pdata->wake_lock, WAKE_LOCK_SUSPEND, "hisi-6402-mbhc");
	wake_lock_init(&pdata->soundtrigger_wake_lock, WAKE_LOCK_SUSPEND, "hisi-6402-soundtrigger");
	mutex_init(&pdata->plug_mutex);
	mutex_init(&pdata->status_mutex);
	mutex_init(&pdata->saradc_mutex);

	/* irq request : pll unlock */
	ret = devm_request_threaded_irq(dev, pdata->irq[HI6402_IRQ_PLL_UNLOCK], NULL,
					hi6402_pll_unlock_handler,
					IRQF_NO_SUSPEND | IRQF_ONESHOT,
					"pll_unlock", pdata);
	if (0 > ret) {
		pr_err("request irq for pll unlock err\n");
		goto pll_unlock_err;
	}
	mutex_lock(&pdata->p_irq->irq_lock);
	hi6402_reg_set_bit(pdata->p_irq, HI6402_MASK_IRQ_REG_2, HI6402_MASK_PLL_UNLOCK_BIT);
	pdata->p_irq->mask2 |= 0x10;
	mutex_unlock(&pdata->p_irq->irq_lock);

	/* irq request : sound triger */
	ret = devm_request_threaded_irq(dev, pdata->irq[HI6402_IRQ_SOUND_TRIGER], NULL,
					hi6402_sound_triger_handler,
					IRQF_NO_SUSPEND | IRQF_ONESHOT,
					"sound_triger", pdata);
	if (0 > ret) {
		pr_err("request irq for sound triger err\n");
		goto sound_triger_err;
	}

	/* irq request : plugout */
	ret = devm_request_threaded_irq(dev, pdata->irq[HI6402_IRQ_PLUGOUT], NULL,
					hi6402_plugout_handler,
					IRQF_NO_SUSPEND | IRQF_ONESHOT,
					"plugout", pdata);
	if (0 > ret) {
		pr_err("request irq for plugout err\n");
		goto plugout_err;
	}

	/* irq request : plugin */
	ret = devm_request_threaded_irq(dev, pdata->irq[HI6402_IRQ_PLUGIN], NULL,
					hi6402_plugin_handler,
					IRQF_NO_SUSPEND | IRQF_ONESHOT,
					"plugin", pdata);
	if (0 > ret) {
		pr_err("request irq for plugin err\n");
		goto plugin_err;
	}

	/* irq request : button up(eco mode) */
	ret = devm_request_threaded_irq(dev, pdata->irq[HI6402_IRQ_BTNUP_ECO], NULL,
					hi6402_btnup_eco_handler,
					IRQF_NO_SUSPEND | IRQF_ONESHOT,
					"btnup_eco", pdata);
	if (0 > ret) {
		pr_err("request irq for btnup eco err\n");
		goto btnup_eco_err;
	}

	/* irq request : button down(eco mode) */
	ret = devm_request_threaded_irq(dev, pdata->irq[HI6402_IRQ_BTNDOWN_ECO], NULL,
					hi6402_btndown_eco_handler,
					IRQF_NO_SUSPEND | IRQF_ONESHOT,
					"btndown_eco", pdata);
	if (0 > ret) {
		pr_err("request irq for btndown eco err\n");
		goto btndown_eco_err;
	}

	/* irq request : button down */
	ret = devm_request_threaded_irq(dev, pdata->irq[HI6402_IRQ_BTNDOWN_COMP1], NULL,
					hi6402_btndown_handler,
					IRQF_NO_SUSPEND | IRQF_ONESHOT,
					"btndown_comp1", pdata);
	if (0 > ret) {
		pr_err("request irq for btndown comp1 err\n");
		goto btndown_comp1_err;
	}

	/* irq request : button up */
	ret = devm_request_threaded_irq(dev, pdata->irq[HI6402_IRQ_BTNUP_COMP1], NULL,
					hi6402_btnup_handler,
					IRQF_NO_SUSPEND | IRQF_ONESHOT,
					"btnup_comp1", pdata);
	if (0 > ret) {
		pr_err("request irq for btnup comp1 err\n");
		goto btnup_comp1_err;
	}

	hi6402_irq_mask_btn_irqs(pdata->p_irq);
	hi6402_irq_clr_btn_irqs(pdata->p_irq);
	
	/* enable hsdet */
	hi6402_irq_write(pdata->p_irq, HI6402_REG_HSDET_CTRL, 0x19);
	hi6402_irq_write(pdata->p_irq, HI6402_MBHC_VREF_REG, 0x8E);

	//register anc hs first
	anc_hs_dev_register(&anc_dev, pdata);

	//register soundtrigger input device.
	ret = soundtrigger_input_init(dev);
	if(ret)
		pr_err("input registor failed: %d\n", ret);

#if 0
	/* check jack at first time */
	if (check_headset_pluged_in(pdata))
		hi6402_plug_in_detect(pdata);
#endif

	pdata->miscdev.minor = MISC_DYNAMIC_MINOR;
	pdata->miscdev.name = "hi6402_mbhc";

	ret = misc_register(&pdata->miscdev);
	if (ret) {
		loge("%s : hisi 6421 spk_device register failed", __FUNCTION__);
		goto btnup_comp1_err;
	}

	if (!dsm_audio_client) {
		dsm_audio_client = dsm_register_client(&dsm_audio);
	}

	pr_info("%s : hi6402 mbhc probe ok \n", __FUNCTION__);

	return ret;

btnup_comp1_err:
	free_irq(pdata->irq[HI6402_IRQ_BTNDOWN_COMP1], pdata);
btndown_comp1_err:
	free_irq(pdata->irq[HI6402_IRQ_BTNDOWN_ECO], pdata);
btndown_eco_err:
	free_irq(pdata->irq[HI6402_IRQ_BTNUP_ECO], pdata);
btnup_eco_err:
	free_irq(pdata->irq[HI6402_IRQ_PLUGIN], pdata);
plugin_err:
	free_irq(pdata->irq[HI6402_IRQ_PLUGOUT], pdata);
plugout_err:
	free_irq(pdata->irq[HI6402_IRQ_SOUND_TRIGER], pdata);
sound_triger_err:
	free_irq(pdata->irq[HI6402_IRQ_PLL_UNLOCK], pdata);
pll_unlock_err:
	wake_lock_destroy(&pdata->soundtrigger_wake_lock);
	wake_lock_destroy(&pdata->wake_lock);
	mutex_destroy(&pdata->plug_mutex);
	mutex_destroy(&pdata->status_mutex);

	return ret;
}
Exemplo n.º 26
0
static int mmi_factory_probe(struct platform_device *pdev)
{
	const struct of_device_id *match;
	struct mmi_factory_info *info;
	int ret;
	int i;

	match = of_match_device(mmi_factory_of_tbl, &pdev->dev);
	if (!match) {
		dev_err(&pdev->dev, "No Match found\n");
		return -ENODEV;
	}

	if (match && match->compatible)
		dev_info(&pdev->dev, "Using %s\n", match->compatible);

	info = mmi_parse_of(pdev);
	if (!info) {
		dev_err(&pdev->dev, "failed to parse node\n");
		return -ENODEV;
	}

	ret = gpio_request_array(info->list, info->num_gpios);
	if (ret) {
		dev_err(&pdev->dev, "failed to request GPIOs\n");
		return ret;
	}

	for (i = 0; i < info->num_gpios; i++) {
		ret = gpio_export(info->list[i].gpio, 1);
		if (ret) {
			dev_err(&pdev->dev, "Failed to export GPIO %s: %d\n",
				info->list[i].label, info->list[i].gpio);
			goto fail;
		}

		ret = gpio_export_link(&pdev->dev, info->list[i].label,
					info->list[i].gpio);
		if (ret) {
			dev_err(&pdev->dev, "Failed to link GPIO %s: %d\n",
				info->list[i].label, info->list[i].gpio);
			goto fail;
		}
	}

	if (!mmi_factory_cable_present()) {
		dev_dbg(&pdev->dev, "factory cable not present\n");
	} else {
		pr_info("Factory Cable Attached at Power up!\n");
		info->factory_cable = 1;
	}

	if (match && match->data) {
		info->dev = *(enum mmi_factory_device_list *)(match->data);
	} else {
		dev_err(&pdev->dev, "failed to find device match\n");
		goto fail;
	}

	if ((info->dev == KUNGPOW) && (info->num_gpios == KP_NUM_GPIOS)) {
		/* Disable Kill if not powered up by a factory cable */
		if (!info->factory_cable)
			gpio_direction_output(info->list[KP_KILL_INDEX].gpio,
						1);
		else {
			ret = device_create_file(&pdev->dev,
						 &dev_attr_usr_rst_sw_dis);
			if (ret)
				dev_err(&pdev->dev,
					"couldn't create usr_rst_sw_dis\n");

			usr_rst_sw_dis_flg = 0;

			ret = device_create_file(&pdev->dev,
						&dev_attr_fac_kill_sw_dis);
			if (ret)
				dev_err(&pdev->dev,
					"couldn't create fac_kill_sw_dis\n");

			fac_kill_sw_dis_flg = 0;
		}

		info->warn_irq = gpio_to_irq(info->list[KP_WARN_INDEX].gpio);
		info->fac_cbl_irq =
			gpio_to_irq(info->list[KP_CABLE_INDEX].gpio);

		INIT_DELAYED_WORK(&info->warn_irq_work, warn_irq_w);
		INIT_DELAYED_WORK(&info->fac_cbl_irq_work, fac_cbl_irq_w);

		if (info->warn_irq) {
			ret = request_irq(info->warn_irq,
					  warn_irq_handler,
					  IRQF_TRIGGER_FALLING,
					  "mmi_factory_warn", info);
			if (ret) {
				dev_err(&pdev->dev,
					"request irq failed for Warn\n");
				goto fail;
			}
		} else {
			ret = -ENODEV;
			dev_err(&pdev->dev, "IRQ for Warn doesn't exist\n");
			goto fail;
		}

		if (info->fac_cbl_irq) {
			ret = request_irq(info->fac_cbl_irq,
					  fac_cbl_irq_handler,
					  IRQF_TRIGGER_RISING |
					  IRQF_TRIGGER_FALLING,
					  "mmi_factory_fac_cbl", info);
			if (ret) {
				dev_err(&pdev->dev,
					"irq failed for Factory Cable\n");
				goto remove_warn;
			}
		} else {
			ret = -ENODEV;
			dev_err(&pdev->dev,
				"IRQ for Factory Cable doesn't exist\n");
			goto remove_warn;
		}
	}

	platform_set_drvdata(pdev, info);

	return 0;

remove_warn:
	free_irq(info->warn_irq, info);
fail:
	gpio_free_array(info->list, info->num_gpios);
	return ret;
}
Exemplo n.º 27
0
static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
{
	struct drm_device *drm = data;
	struct device_node *np = dev->of_node;
	const struct of_device_id *of_id =
			of_match_device(imx_ldb_dt_ids, dev);
	struct device_node *child;
	const u8 *edidp;
	struct imx_ldb *imx_ldb;
	int datawidth;
	int mapping;
	int dual;
	int ret;
	int i;

	imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL);
	if (!imx_ldb)
		return -ENOMEM;

	imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
	if (IS_ERR(imx_ldb->regmap)) {
		dev_err(dev, "failed to get parent regmap\n");
		return PTR_ERR(imx_ldb->regmap);
	}

	imx_ldb->dev = dev;

	if (of_id)
		imx_ldb->lvds_mux = of_id->data;

	dual = of_property_read_bool(np, "fsl,dual-channel");
	if (dual)
		imx_ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN;

	/*
	 * There are three different possible clock mux configurations:
	 * i.MX53:  ipu1_di0_sel, ipu1_di1_sel
	 * i.MX6q:  ipu1_di0_sel, ipu1_di1_sel, ipu2_di0_sel, ipu2_di1_sel
	 * i.MX6dl: ipu1_di0_sel, ipu1_di1_sel, lcdif_sel
	 * Map them all to di0_sel...di3_sel.
	 */
	for (i = 0; i < 4; i++) {
		char clkname[16];

		sprintf(clkname, "di%d_sel", i);
		imx_ldb->clk_sel[i] = devm_clk_get(imx_ldb->dev, clkname);
		if (IS_ERR(imx_ldb->clk_sel[i])) {
			ret = PTR_ERR(imx_ldb->clk_sel[i]);
			imx_ldb->clk_sel[i] = NULL;
			break;
		}
	}
	if (i == 0)
		return ret;

	for_each_child_of_node(np, child) {
		struct imx_ldb_channel *channel;
		struct device_node *panel_node;

		ret = of_property_read_u32(child, "reg", &i);
		if (ret || i < 0 || i > 1)
			return -EINVAL;

		if (dual && i > 0) {
			dev_warn(dev, "dual-channel mode, ignoring second output\n");
			continue;
		}

		if (!of_device_is_available(child))
			continue;

		channel = &imx_ldb->channel[i];
		channel->ldb = imx_ldb;
		channel->chno = i;
		channel->child = child;

		edidp = of_get_property(child, "edid", &channel->edid_len);
		if (edidp) {
			channel->edid = kmemdup(edidp, channel->edid_len,
						GFP_KERNEL);
		} else {
			ret = of_get_drm_display_mode(child, &channel->mode, 0);
			if (!ret)
				channel->mode_valid = 1;
		}

		ret = of_property_read_u32(child, "fsl,data-width", &datawidth);
		if (ret)
			datawidth = 0;
		else if (datawidth != 18 && datawidth != 24)
			return -EINVAL;

		mapping = of_get_data_mapping(child);
		switch (mapping) {
		case LVDS_BIT_MAP_SPWG:
			if (datawidth == 24) {
				if (i == 0 || dual)
					imx_ldb->ldb_ctrl |=
						LDB_DATA_WIDTH_CH0_24;
				if (i == 1 || dual)
					imx_ldb->ldb_ctrl |=
						LDB_DATA_WIDTH_CH1_24;
			}
			break;
		case LVDS_BIT_MAP_JEIDA:
			if (datawidth == 18) {
				dev_err(dev, "JEIDA standard only supported in 24 bit\n");
				return -EINVAL;
			}
			if (i == 0 || dual)
				imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 |
					LDB_BIT_MAP_CH0_JEIDA;
			if (i == 1 || dual)
				imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 |
					LDB_BIT_MAP_CH1_JEIDA;
			break;
		default:
			dev_err(dev, "data mapping not specified or invalid\n");
			return -EINVAL;
		}

		panel_node = of_parse_phandle(child, "fsl,panel", 0);
		if (panel_node)
			channel->panel = of_drm_find_panel(panel_node);

		ret = imx_ldb_register(drm, channel);
		if (ret)
			return ret;
	}

	dev_set_drvdata(dev, imx_ldb);

	return 0;
}
static int bimc_bwmon_driver_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct bwmon *m;
	const struct of_device_id *id;
	int ret;
	u32 data;

	m = devm_kzalloc(dev, sizeof(*m), GFP_KERNEL);
	if (!m)
		return -ENOMEM;
	m->dev = dev;

	ret = of_property_read_u32(dev->of_node, "qcom,mport", &data);
	if (ret) {
		dev_err(dev, "mport not found!\n");
		return ret;
	}
	m->mport = data;

	id = of_match_device(match_table, dev);
	if (!id) {
		dev_err(dev, "Unknown device type!\n");
		return -ENODEV;
	}
	m->spec = id->data;

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base");
	if (!res) {
		dev_err(dev, "base not found!\n");
		return -EINVAL;
	}
	m->base = devm_ioremap(dev, res->start, resource_size(res));
	if (!m->base) {
		dev_err(dev, "Unable map base!\n");
		return -ENOMEM;
	}

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "global_base");
	if (!res) {
		dev_err(dev, "global_base not found!\n");
		return -EINVAL;
	}
	m->global_base = devm_ioremap(dev, res->start, resource_size(res));
	if (!m->global_base) {
		dev_err(dev, "Unable map global_base!\n");
		return -ENOMEM;
	}

	m->irq = platform_get_irq(pdev, 0);
	if (m->irq < 0) {
		dev_err(dev, "Unable to get IRQ number\n");
		return m->irq;
	}

	m->hw.of_node = of_parse_phandle(dev->of_node, "qcom,target-dev", 0);
	if (!m->hw.of_node)
		return -EINVAL;
	m->hw.start_hwmon = &start_bw_hwmon,
	m->hw.stop_hwmon = &stop_bw_hwmon,
	m->hw.suspend_hwmon = &suspend_bw_hwmon,
	m->hw.resume_hwmon = &resume_bw_hwmon,
	m->hw.meas_bw_and_set_irq = &meas_bw_and_set_irq,

	ret = register_bw_hwmon(dev, &m->hw);
	if (ret) {
		dev_err(dev, "Dev BW hwmon registration failed\n");
		return ret;
	}

	return 0;
}
Exemplo n.º 29
0
static int jz4740_rtc_probe(struct platform_device *pdev)
{
	int ret;
	struct jz4740_rtc *rtc;
	uint32_t scratchpad;
	struct resource *mem;
	const struct platform_device_id *id = platform_get_device_id(pdev);
	const struct of_device_id *of_id = of_match_device(
			jz4740_rtc_of_match, &pdev->dev);
	struct device_node *np = pdev->dev.of_node;

	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
	if (!rtc)
		return -ENOMEM;

	if (of_id)
		rtc->type = (enum jz4740_rtc_type)of_id->data;
	else
		rtc->type = id->driver_data;

	rtc->irq = platform_get_irq(pdev, 0);
	if (rtc->irq < 0) {
		dev_err(&pdev->dev, "Failed to get platform irq\n");
		return -ENOENT;
	}

	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	rtc->base = devm_ioremap_resource(&pdev->dev, mem);
	if (IS_ERR(rtc->base))
		return PTR_ERR(rtc->base);

	rtc->clk = devm_clk_get(&pdev->dev, "rtc");
	if (IS_ERR(rtc->clk)) {
		dev_err(&pdev->dev, "Failed to get RTC clock\n");
		return PTR_ERR(rtc->clk);
	}

	spin_lock_init(&rtc->lock);

	platform_set_drvdata(pdev, rtc);

	device_init_wakeup(&pdev->dev, 1);

	rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
					&jz4740_rtc_ops, THIS_MODULE);
	if (IS_ERR(rtc->rtc)) {
		ret = PTR_ERR(rtc->rtc);
		dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret);
		return ret;
	}

	ret = devm_request_irq(&pdev->dev, rtc->irq, jz4740_rtc_irq, 0,
				pdev->name, rtc);
	if (ret) {
		dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret);
		return ret;
	}

	scratchpad = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_SCRATCHPAD);
	if (scratchpad != 0x12345678) {
		ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678);
		ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0);
		if (ret) {
			dev_err(&pdev->dev, "Could not write write to RTC registers\n");
			return ret;
		}
	}

	if (np && of_device_is_system_power_controller(np)) {
		if (!pm_power_off) {
			/* Default: 60ms */
			rtc->reset_pin_assert_time = 60;
			of_property_read_u32(np, "reset-pin-assert-time-ms",
					     &rtc->reset_pin_assert_time);

			/* Default: 100ms */
			rtc->min_wakeup_pin_assert_time = 100;
			of_property_read_u32(np,
					     "min-wakeup-pin-assert-time-ms",
					     &rtc->min_wakeup_pin_assert_time);

			dev_for_power_off = &pdev->dev;
			pm_power_off = jz4740_rtc_power_off;
		} else {
			dev_warn(&pdev->dev,
				 "Poweroff handler already present!\n");
		}
	}

	return 0;
}
Exemplo n.º 30
0
static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
{
	const struct of_device_id *match;
	const struct sdhci_tegra_soc_data *soc_data;
	struct sdhci_host *host;
	struct sdhci_pltfm_host *pltfm_host;
	struct tegra_sdhci_platform_data *plat;
	struct sdhci_tegra *tegra_host;
	struct clk *clk;
	int rc;

	match = of_match_device(sdhci_tegra_dt_match, &pdev->dev);
	if (match)
		soc_data = match->data;
	else
		soc_data = &soc_data_tegra20;

	host = sdhci_pltfm_init(pdev, soc_data->pdata);
	if (IS_ERR(host))
		return PTR_ERR(host);

	pltfm_host = sdhci_priv(host);

	plat = pdev->dev.platform_data;

	if (plat == NULL)
		plat = sdhci_tegra_dt_parse_pdata(pdev);

	if (plat == NULL) {
		dev_err(mmc_dev(host->mmc), "missing platform data\n");
		rc = -ENXIO;
		goto err_no_plat;
	}

	tegra_host = devm_kzalloc(&pdev->dev, sizeof(*tegra_host), GFP_KERNEL);
	if (!tegra_host) {
		dev_err(mmc_dev(host->mmc), "failed to allocate tegra_host\n");
		rc = -ENOMEM;
		goto err_no_plat;
	}

	tegra_host->plat = plat;
	tegra_host->soc_data = soc_data;

	pltfm_host->priv = tegra_host;

	if (gpio_is_valid(plat->power_gpio)) {
		rc = gpio_request(plat->power_gpio, "sdhci_power");
		if (rc) {
			dev_err(mmc_dev(host->mmc),
				"failed to allocate power gpio\n");
			goto err_power_req;
		}
		tegra_gpio_enable(plat->power_gpio);
		gpio_direction_output(plat->power_gpio, 1);
	}

	if (gpio_is_valid(plat->cd_gpio)) {
		rc = gpio_request(plat->cd_gpio, "sdhci_cd");
		if (rc) {
			dev_err(mmc_dev(host->mmc),
				"failed to allocate cd gpio\n");
			goto err_cd_req;
		}
		tegra_gpio_enable(plat->cd_gpio);
		gpio_direction_input(plat->cd_gpio);

		rc = request_irq(gpio_to_irq(plat->cd_gpio), carddetect_irq,
				 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
				 mmc_hostname(host->mmc), host);

		if (rc)	{
			dev_err(mmc_dev(host->mmc), "request irq error\n");
			goto err_cd_irq_req;
		}

	}

	if (gpio_is_valid(plat->wp_gpio)) {
		rc = gpio_request(plat->wp_gpio, "sdhci_wp");
		if (rc) {
			dev_err(mmc_dev(host->mmc),
				"failed to allocate wp gpio\n");
			goto err_wp_req;
		}
		tegra_gpio_enable(plat->wp_gpio);
		gpio_direction_input(plat->wp_gpio);
	}

	clk = clk_get(mmc_dev(host->mmc), NULL);
	if (IS_ERR(clk)) {
		dev_err(mmc_dev(host->mmc), "clk err\n");
		rc = PTR_ERR(clk);
		goto err_clk_get;
	}
	clk_enable(clk);
	pltfm_host->clk = clk;

	host->mmc->pm_caps = plat->pm_flags;

	if (plat->is_8bit)
		host->mmc->caps |= MMC_CAP_8_BIT_DATA;

	rc = sdhci_add_host(host);
	if (rc)
		goto err_add_host;

	return 0;

err_add_host:
	clk_disable(pltfm_host->clk);
	clk_put(pltfm_host->clk);
err_clk_get:
	if (gpio_is_valid(plat->wp_gpio)) {
		tegra_gpio_disable(plat->wp_gpio);
		gpio_free(plat->wp_gpio);
	}
err_wp_req:
	if (gpio_is_valid(plat->cd_gpio))
		free_irq(gpio_to_irq(plat->cd_gpio), host);
err_cd_irq_req:
	if (gpio_is_valid(plat->cd_gpio)) {
		tegra_gpio_disable(plat->cd_gpio);
		gpio_free(plat->cd_gpio);
	}
err_cd_req:
	if (gpio_is_valid(plat->power_gpio)) {
		tegra_gpio_disable(plat->power_gpio);
		gpio_free(plat->power_gpio);
	}
err_power_req:
err_no_plat:
	sdhci_pltfm_free(pdev);
	return rc;
}