Ejemplo n.º 1
0
/* Manually detach a device from its associated driver. */
static ssize_t driver_unbind(struct device_driver *drv,
                             const char *buf, size_t count)
{
    struct bus_type *bus = bus_get(drv->bus);
    struct device *dev;
    int err = -ENODEV;

    dev = bus_find_device_by_name(bus, NULL, buf);
    if (dev && dev->driver == drv) {
        if (dev->parent)	/* Needed for USB */
            device_lock(dev->parent);
        device_release_driver(dev);
        if (dev->parent)
            device_unlock(dev->parent);
        err = count;
    }
    put_device(dev);
    bus_put(bus);
    return err;
}
Ejemplo n.º 2
0
static struct platform_device *hsi_get_hsi_platform_device(void)
{
	struct device *dev;
	struct platform_device *pdev;

	/* HSI_TODO: handle platform device id (or port) (0/1) */
	dev = bus_find_device_by_name(&platform_bus_type, NULL,
					OMAP_HSI_PLATFORM_DEVICE_NAME);
	if (!dev) {
		pr_debug("Could not find platform device %s\n",
		       OMAP_HSI_PLATFORM_DEVICE_NAME);
		return 0;
	}

	if (!dev->driver) {
		/* Could not find driver for platform device. */
		return 0;
	}

	pdev = to_platform_device(dev);

	return pdev;
}
Ejemplo n.º 3
0
Archivo: bus.c Proyecto: Anjali05/linux
/*
 * Manually attach a device to a driver.
 * Note: the driver must want to bind to the device,
 * it is not possible to override the driver's id table.
 */
static ssize_t bind_store(struct device_driver *drv, const char *buf,
			  size_t count)
{
	struct bus_type *bus = bus_get(drv->bus);
	struct device *dev;
	int err = -ENODEV;

	dev = bus_find_device_by_name(bus, NULL, buf);
	if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
		err = device_driver_attach(drv, dev);

		if (err > 0) {
			/* success */
			err = count;
		} else if (err == 0) {
			/* driver didn't accept device */
			err = -ENODEV;
		}
	}
	put_device(dev);
	bus_put(bus);
	return err;
}
Ejemplo n.º 4
0
/*====================================================================
FUNCTION       find_spi_device  
DESCRIPTION 
DEPENDENCIES
RETURN VALUE
SIDE EFFECTS
======================================================================*/
static struct spi_device* find_spi_device(int bus_num)
{
  struct spi_master *spi_master;
  struct spi_device *spi_device;
  struct device *pdev;
  char buff[64];

  spi_master = spi_busnum_to_master(bus_num);
  if (!spi_master) {
    TDMB_MSG_SPI("[%s] spi_busnum_to_master(%d) returned NULL\n", __func__, bus_num);
    return NULL;
  }

  spi_device = spi_alloc_device(spi_master);
  if (!spi_device) {
    put_device(&spi_master->dev);
    TDMB_MSG_SPI("[%s] spi_alloc_device() failed\n", __func__);
    return NULL;
  }

  /* specify a chip select line */
  spi_device->chip_select = 0;

  snprintf(buff, sizeof(buff), "%s.%u",
      dev_name(&spi_device->master->dev),
      spi_device->chip_select);

  pdev = bus_find_device_by_name(spi_device->dev.bus, NULL, buff);

  //if (pdev) {
  //  TCDBG("spi_device :0x%X\n", (unsigned int)spi_device);
  //}

  put_device(&spi_master->dev);
  return spi_device;
}
Ejemplo n.º 5
0
static int cc2520_spi_add_to_bus(void)
{
    struct spi_master *spi_master;
    struct spi_device *spi_device;
    struct device *pdev;
    char buff[64];
    int status = 0;

    spi_master = spi_busnum_to_master(SPI_BUS);
    if (!spi_master) {
        printk(KERN_ALERT "[cc2520] - spi_busnum_to_master(%d) returned NULL\n",
            SPI_BUS);
        printk(KERN_ALERT "[cc2520] - Missing modprobe spi-bcm2708?\n");
        return -1;
    }

    spi_device = spi_alloc_device(spi_master);
    if (!spi_device) {
        put_device(&spi_master->dev);
        printk(KERN_ALERT "[cc2520] - spi_alloc_device() failed\n");
        return -1;
    }

    spi_device->chip_select = SPI_BUS_CS0;

    /* Check whether this SPI bus.cs is already claimed */
    snprintf(buff, sizeof(buff), "%s.%u", 
            dev_name(&spi_device->master->dev),
            spi_device->chip_select);

    pdev = bus_find_device_by_name(spi_device->dev.bus, NULL, buff);

    if (pdev) {
        if (pdev->driver != NULL) {
            printk(KERN_INFO
                "[cc2520] - Driver [%s] already registered for %s. Nuking from orbit.\n",
                pdev->driver->name, buff);            
        }
        else {
            printk(KERN_INFO
                "[cc2520] - Previous driver registered with no loaded module. Nuking from orbit.\n");
        }

        device_unregister(pdev);
    }

    spi_device->max_speed_hz = SPI_BUS_SPEED;
    spi_device->mode = SPI_MODE_0;
    spi_device->bits_per_word = 8;
    spi_device->irq = -1;

    spi_device->controller_state = NULL;
    spi_device->controller_data = NULL;
    strlcpy(spi_device->modalias, cc2520_name, SPI_NAME_SIZE);

    status = spi_add_device(spi_device);        
    if (status < 0) {   
        spi_dev_put(spi_device);
        printk(KERN_ALERT "[cc2520] - spi_add_device() failed: %d\n", 
            status);        
    }               

    put_device(&spi_master->dev);
    return status;
}
Ejemplo n.º 6
0
void __init stx7108_configure_pci(struct stm_plat_pci_config *pci_conf)
{
	struct sysconf_field *sc;
	int i;

	/* LLA clocks have these horrible names... */
	pci_conf->clk_name = "CLKA_PCI";

	/* REQ0 is actually wired to REQ3 to work around NAND problems */
	pci_conf->req0_to_req3 = 1;
	BUG_ON(pci_conf->req_gnt[3] != PCI_PIN_UNUSED);

	/* Fill in the default values */
	if (!pci_conf->ad_override_default) {
		pci_conf->ad_threshold = 5;
		pci_conf->ad_read_ahead = 1;
		pci_conf->ad_chunks_in_msg = 0;
		pci_conf->ad_pcks_in_chunk = 0;
		pci_conf->ad_trigger_mode = 1;
		pci_conf->ad_max_opcode = 5;
		pci_conf->ad_posted = 1;
	}

	/* Copy over platform specific data to driver */
	stx7108_pci_device.dev.platform_data = pci_conf;

#if defined(CONFIG_PM)
#warning TODO: PCI Power Management
#endif
	/* Claim and power up the PCI cell */
	sc = sysconf_claim(SYS_CFG_BANK2, 30, 2, 2, "PCI_PWR_DWN_REQ");
	sysconf_write(sc, 0); /* We will need to stash this somewhere
				 for power management. */
	sc = sysconf_claim(SYS_STA_BANK2, 1, 2, 2, "PCI_PWR_DWN_GRANT");
	while (sysconf_read(sc))
		cpu_relax(); /* Loop until powered up */

	/* Configure the REQ/GNT[1..2], muxed with PIOs */
	for (i = 1; i <= 2; i++) {
		switch (pci_conf->req_gnt[i]) {
		case PCI_PIN_DEFAULT:
			if (stm_pad_claim(&stx7108_pci_reqgnt_pad_config[i],
					"PCI") == NULL) {
				printk(KERN_ERR "Failed to claim REQ/GNT%d "
						"pads!\n", i);
				BUG();
			}
			break;
		case PCI_PIN_UNUSED:
			/* Unused is unused - nothing to do */
			break;
		default:
			/* No alternative here... */
			BUG();
			break;
		}
	}

	/* Configure INTA..D interrupts */
	for (i = 0; i < 4; i++) {
		switch (pci_conf->pci_irq[i]) {
		case PCI_PIN_DEFAULT:
			if (stm_pad_claim(&stx7108_pci_int_pad_config[i],
						"PCI") == NULL) {
				printk(KERN_ERR "Failed to claim INT%c pad!\n",
						'A' + i);
				BUG();
			}
			set_irq_type(ILC_IRQ(122 + i), IRQ_TYPE_LEVEL_LOW);
			break;
		case PCI_PIN_ALTERNATIVE:
			/* There is no alternative here ;-) */
			BUG();
			break;
		default:
			/* Unused or interrupt number passed, nothing to do */
			break;
		}
	}

	/* Configure the SERR interrupt (if wired up) */
	switch (pci_conf->serr_irq) {
	case PCI_PIN_DEFAULT:
		if (gpio_request(STX7108_PIO_PCI_SERR, "PCI_SERR#") == 0) {
			gpio_direction_input(STX7108_PIO_PCI_SERR);
			pci_conf->serr_irq = gpio_to_irq(STX7108_PIO_PCI_SERR);
			set_irq_type(pci_conf->serr_irq, IRQ_TYPE_LEVEL_LOW);
		} else {
			printk(KERN_WARNING "%s(): Failed to claim PCI SERR# "
					"PIO!\n", __func__);
			pci_conf->serr_irq = PCI_PIN_UNUSED;
		}
		break;
	case PCI_PIN_ALTERNATIVE:
		/* No alternative here */
		BUG();
		pci_conf->serr_irq = PCI_PIN_UNUSED;
		break;
	}
	if (pci_conf->serr_irq != PCI_PIN_UNUSED) {
		struct resource *res =
			platform_get_resource_byname(&stx7108_pci_device,
					IORESOURCE_IRQ, "pci serr");

		BUG_ON(!res);
		res->start = pci_conf->serr_irq;
		res->end = pci_conf->serr_irq;
	}

	/* LOCK is not claimed as is totally pointless, the SOCs do not
	 * support any form of coherency */

	stx7108_pci_device.dev.parent =
		bus_find_device_by_name(&platform_bus_type, NULL, "emi");
	platform_device_register(&stx7108_pci_device);
}
int __init e1853_panel_init(void)
{
	bool has_ebb = false;
	int err;
#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC)
	struct resource *res;
	struct platform_device *phost1x = NULL;
#endif
	bool is_dt = of_have_populated_dt();

	if (tegra_is_board(NULL, "61861", NULL, NULL, NULL)) {
		has_ebb = true;
		if (tegra_is_board(NULL, "61227", NULL, NULL, NULL)) {
			e1853_config_CLAA101WB03_lcd();
			e1853_touch_init();
		}
	}

	e1853_carveouts[1].base = tegra_carveout_start;
	e1853_carveouts[1].size = tegra_carveout_size;
	tegra_disp1_device.dev.platform_data = &e1853_disp1_pdata;
	tegra_disp2_device.dev.platform_data = &e1853_hdmi_pdata;

	err = platform_add_devices(e1853_gfx_devices,
		ARRAY_SIZE(e1853_gfx_devices));

#ifdef CONFIG_TEGRA_GRHOST
	if (!is_dt)
		phost1x = tegra3_register_host1x_devices();
	else
		phost1x = to_platform_device(bus_find_device_by_name(
			&platform_bus_type, NULL, "host1x"));
	if (!phost1x) {
		pr_err("host1x devices registration failed\n");
		return -EINVAL;
	}
#endif

#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC)
	res = platform_get_resource_byname(&tegra_disp1_device,
					 IORESOURCE_MEM, "fbmem");
	if (res) {
		res->start = tegra_fb_start;
		res->end = tegra_fb_start + tegra_fb_size - 1;
	}

	/*
	 * If the bootloader fb is valid, copy it to the fb, or else
	 * clear fb to avoid garbage on dispaly1.
	 */
	if (tegra_bootloader_fb_size)
		__tegra_move_framebuffer(&e1853_nvmap_device,
				tegra_fb_start, tegra_bootloader_fb_start,
				min(tegra_fb_size, tegra_bootloader_fb_size));
	else
		__tegra_clear_framebuffer(&e1853_nvmap_device,
					  tegra_fb_start, tegra_fb_size);

	if (!err) {
		tegra_disp1_device.dev.parent = &phost1x->dev;
		err = platform_device_register(&tegra_disp1_device);
	}

	res = platform_get_resource_byname(&tegra_disp2_device,
					 IORESOURCE_MEM, "fbmem");
	if (res) {
		res->start = tegra_fb2_start;
		res->end = tegra_fb2_start + tegra_fb2_size - 1;
	}

	/*
	 * If the bootloader fb2 is valid, copy it to the fb2, or else
	 * clear fb2 to avoid garbage on dispaly2.
	 */
	if (tegra_bootloader_fb2_size)
		__tegra_move_framebuffer(&e1853_nvmap_device,
			tegra_fb2_start, tegra_bootloader_fb2_start,
			min(tegra_fb2_size, tegra_bootloader_fb2_size));
	else
		__tegra_clear_framebuffer(&e1853_nvmap_device,
					  tegra_fb2_start, tegra_fb2_size);

	if (!err) {
		tegra_disp2_device.dev.parent = &phost1x->dev;
		err = platform_device_register(&tegra_disp2_device);
	}
#endif

#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_NVAVP)
	if (!err) {
		nvavp_device.dev.parent = &phost1x->dev;
		err = platform_device_register(&nvavp_device);
	}
#endif

	if (has_ebb) {
		if (!err)
			i2c_register_board_info(1, lvds_ser_info, 1);
	}

	return err;
}
Ejemplo n.º 8
0
static int snd_byt_rt5651_mc_probe(struct platform_device *pdev)
{
	const char * const mic_name[] = { "dmic", "in1", "in2", "in12" };
	struct byt_rt5651_private *priv;
	struct snd_soc_acpi_mach *mach;
	struct device *codec_dev;
	const char *i2c_name = NULL;
	const char *hp_swapped;
	bool is_bytcr = false;
	int ret_val = 0;
	int dai_index = 0;
	int i;

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

	/* register the soc card */
	byt_rt5651_card.dev = &pdev->dev;

	mach = byt_rt5651_card.dev->platform_data;
	snd_soc_card_set_drvdata(&byt_rt5651_card, priv);

	/* fix index of codec dai */
	for (i = 0; i < ARRAY_SIZE(byt_rt5651_dais); i++) {
		if (!strcmp(byt_rt5651_dais[i].codec_name, "i2c-10EC5651:00")) {
			dai_index = i;
			break;
		}
	}

	/* fixup codec name based on HID */
	i2c_name = acpi_dev_get_first_match_name(mach->id, NULL, -1);
	if (!i2c_name) {
		dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
		return -ENODEV;
	}
	snprintf(byt_rt5651_codec_name, sizeof(byt_rt5651_codec_name),
		"%s%s", "i2c-", i2c_name);
	byt_rt5651_dais[dai_index].codec_name = byt_rt5651_codec_name;

	codec_dev = bus_find_device_by_name(&i2c_bus_type, NULL,
					    byt_rt5651_codec_name);
	if (!codec_dev)
		return -EPROBE_DEFER;

	/*
	 * swap SSP0 if bytcr is detected
	 * (will be overridden if DMI quirk is detected)
	 */
	if (x86_match_cpu(baytrail_cpu_ids)) {
		struct sst_platform_info *p_info = mach->pdata;
		const struct sst_res_info *res_info = p_info->res_info;

		if (res_info->acpi_ipc_irq_index == 0)
			is_bytcr = true;
	}

	if (is_bytcr) {
		/*
		 * Baytrail CR platforms may have CHAN package in BIOS, try
		 * to find relevant routing quirk based as done on Windows
		 * platforms. We have to read the information directly from the
		 * BIOS, at this stage the card is not created and the links
		 * with the codec driver/pdata are non-existent
		 */

		struct acpi_chan_package chan_package;

		/* format specified: 2 64-bit integers */
		struct acpi_buffer format = {sizeof("NN"), "NN"};
		struct acpi_buffer state = {0, NULL};
		struct snd_soc_acpi_package_context pkg_ctx;
		bool pkg_found = false;

		state.length = sizeof(chan_package);
		state.pointer = &chan_package;

		pkg_ctx.name = "CHAN";
		pkg_ctx.length = 2;
		pkg_ctx.format = &format;
		pkg_ctx.state = &state;
		pkg_ctx.data_valid = false;

		pkg_found = snd_soc_acpi_find_package_from_hid(mach->id,
							       &pkg_ctx);
		if (pkg_found) {
			if (chan_package.aif_value == 1) {
				dev_info(&pdev->dev, "BIOS Routing: AIF1 connected\n");
				byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF1;
			} else  if (chan_package.aif_value == 2) {
				dev_info(&pdev->dev, "BIOS Routing: AIF2 connected\n");
				byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
			} else {
				dev_info(&pdev->dev, "BIOS Routing isn't valid, ignored\n");
				pkg_found = false;
			}
		}

		if (!pkg_found) {
			/* no BIOS indications, assume SSP0-AIF2 connection */
			byt_rt5651_quirk |= BYT_RT5651_SSP0_AIF2;
		}
	}

	/* check quirks before creating card */
	dmi_check_system(byt_rt5651_quirk_table);

	/* Must be called before register_card, also see declaration comment. */
	ret_val = byt_rt5651_add_codec_device_props(codec_dev);
	if (ret_val) {
		put_device(codec_dev);
		return ret_val;
	}

	/* Cherry Trail devices use an external amplifier enable gpio */
	if (x86_match_cpu(cherrytrail_cpu_ids)) {
		snd_byt_rt5651_mc_add_amp_en_gpio_mapping(codec_dev);
		priv->ext_amp_gpio = devm_fwnode_get_index_gpiod_from_child(
						&pdev->dev, "ext-amp-enable", 0,
						codec_dev->fwnode,
						GPIOD_OUT_LOW, "speaker-amp");
		if (IS_ERR(priv->ext_amp_gpio)) {
			ret_val = PTR_ERR(priv->ext_amp_gpio);
			switch (ret_val) {
			case -ENOENT:
				priv->ext_amp_gpio = NULL;
				break;
			default:
				dev_err(&pdev->dev, "Failed to get ext-amp-enable GPIO: %d\n",
					ret_val);
				/* fall through */
			case -EPROBE_DEFER:
				put_device(codec_dev);
				return ret_val;
			}
		}
	}

	put_device(codec_dev);

	log_quirks(&pdev->dev);

	if ((byt_rt5651_quirk & BYT_RT5651_SSP2_AIF2) ||
	    (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
		/* fixup codec aif name */
		snprintf(byt_rt5651_codec_aif_name,
			sizeof(byt_rt5651_codec_aif_name),
			"%s", "rt5651-aif2");

		byt_rt5651_dais[dai_index].codec_dai_name =
			byt_rt5651_codec_aif_name;
	}

	if ((byt_rt5651_quirk & BYT_RT5651_SSP0_AIF1) ||
	    (byt_rt5651_quirk & BYT_RT5651_SSP0_AIF2)) {
		/* fixup cpu dai name name */
		snprintf(byt_rt5651_cpu_dai_name,
			sizeof(byt_rt5651_cpu_dai_name),
			"%s", "ssp0-port");

		byt_rt5651_dais[dai_index].cpu_dai_name =
			byt_rt5651_cpu_dai_name;
	}

	if (byt_rt5651_quirk & BYT_RT5651_MCLK_EN) {
		priv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
		if (IS_ERR(priv->mclk)) {
			ret_val = PTR_ERR(priv->mclk);
			dev_err(&pdev->dev,
				"Failed to get MCLK from pmc_plt_clk_3: %d\n",
				ret_val);
			/*
			 * Fall back to bit clock usage for -ENOENT (clock not
			 * available likely due to missing dependencies), bail
			 * for all other errors, including -EPROBE_DEFER
			 */
			if (ret_val != -ENOENT)
				return ret_val;
			byt_rt5651_quirk &= ~BYT_RT5651_MCLK_EN;
		}
	}

	if (byt_rt5651_quirk & BYT_RT5651_HP_LR_SWAPPED)
		hp_swapped = "-hp-swapped";
	else
		hp_swapped = "";

	snprintf(byt_rt5651_long_name, sizeof(byt_rt5651_long_name),
		 "bytcr-rt5651-%s-spk-%s-mic%s",
		 (byt_rt5651_quirk & BYT_RT5651_MONO_SPEAKER) ?
			"mono" : "stereo",
		 mic_name[BYT_RT5651_MAP(byt_rt5651_quirk)], hp_swapped);
	byt_rt5651_card.long_name = byt_rt5651_long_name;

	ret_val = devm_snd_soc_register_card(&pdev->dev, &byt_rt5651_card);

	if (ret_val) {
		dev_err(&pdev->dev, "devm_snd_soc_register_card failed %d\n",
			ret_val);
		return ret_val;
	}
	platform_set_drvdata(pdev, &byt_rt5651_card);
	return ret_val;
}
Ejemplo n.º 9
0
static int __init add_pcd8544_device_to_bus(void)
{
	struct spi_master *spi_master;
	struct spi_device *spi_device;
	struct device *pdev;
	char buff[64];
	int status = 0;

	spi_master = spi_busnum_to_master(SPI_BUS);
	if (!spi_master) {
		printk(KERN_ALERT "spi_busnum_to_master(%d) returned NULL\n",
			SPI_BUS);
		printk(KERN_ALERT "Missing modprobe omap2_mcspi?\n");
		return -1;
	}

	spi_device = spi_alloc_device(spi_master);
	if (!spi_device) {
		put_device(&spi_master->dev);
		printk(KERN_ALERT "spi_alloc_device() failed\n");
		return -1;
	}

	spi_device->chip_select = SPI_BUS_CS;

	/* Check whether this SPI bus.cs is already claimed */
	snprintf(buff, sizeof(buff), "%s.%u", 
			dev_name(&spi_device->master->dev),
			spi_device->chip_select);

	pdev = bus_find_device_by_name(spi_device->dev.bus, NULL, buff);
 	if (pdev) {
		/* We are not going to use this spi_device, so free it */ 
		spi_dev_put(spi_device);
		
		/* 
		 * There is already a device configured for this bus.cs  
		 * It is okay if it us, otherwise complain and fail.
		 */
		if (pdev->driver && pdev->driver->name && 
				strcmp(this_driver_name, pdev->driver->name)) {
			printk(KERN_ALERT 
				"Driver [%s] already registered for %s\n",
				pdev->driver->name, buff);
			status = -1;
		} 
	} else {
		spi_device->max_speed_hz = SPI_BUS_SPEED;
		spi_device->mode = SPI_MODE_0;
		spi_device->bits_per_word = 8;
		spi_device->irq = -1;
		spi_device->controller_state = NULL;
		spi_device->controller_data = NULL;
		strlcpy(spi_device->modalias, this_driver_name, SPI_NAME_SIZE);
		
		status = spi_add_device(spi_device);		
		if (status < 0) {	
			spi_dev_put(spi_device);
			printk(KERN_ALERT "spi_add_device() failed: %d\n", 
				status);		
		}				
	}

	put_device(&spi_master->dev);

	return status;
}
Ejemplo n.º 10
0
Archivo: spi.c Proyecto: mangOH/mangOH
static int __init mt7697spi_init(void)
{
	char str[32];
	struct spi_master *master = NULL;
	struct device *dev;
	struct spi_device *spi;
	struct mt7697q_info *qinfo = NULL;
	int bus_num = MT7697_SPI_BUS_NUM;
	int ret = 0;

	pr_info(DRVNAME" %s(): '%s' initialize\n", __func__, DRVNAME);

	while (!master && (bus_num >= 0)) {
		master = spi_busnum_to_master(bus_num);
		if (!master)
			bus_num--;
	}

	if (!master) {
		pr_err(DRVNAME" spi_busnum_to_master() failed\n");
		ret = -EINVAL;
		goto cleanup;
	}

	ret = cp2130_update_ch_config(master, MT7697_SPI_CONFIG);
	if (ret < 0) {
		dev_err(&master->dev,
		        "%s(): cp2130_update_ch_config() failed(%d)\n",
		        __func__, ret);
		goto cleanup;
	}

	snprintf(str, sizeof(str), "%s.%u", dev_name(&master->dev),
	         MT7697_SPI_CS);
	dev_info(&master->dev, "%s(): find SPI device('%s')\n", __func__, str);
	dev = bus_find_device_by_name(&spi_bus_type, NULL, str);
	if (!dev) {
		dev_err(&master->dev,
		        "%s(): bus_find_device_by_name('%s') failed\n",
		        __func__, str);

		ret = -EINVAL;
		goto cleanup;
	}

	spi = to_spi_device(dev);
	if (!spi) {
		dev_err(&master->dev, "%s(): get SPI device failed\n",
		        __func__);
		ret = -EINVAL;
		goto cleanup;
	}

	dev_info(&master->dev, "%s(): dev('%s') mode(%d) max speed(%d) "
	         "CS(%d) bits/word(%d)\n",
	         __func__, spi->modalias, spi->mode, spi->max_speed_hz,
	         spi->chip_select, spi->bits_per_word);

	qinfo = kzalloc(sizeof(struct mt7697q_info), GFP_KERNEL);
	if (!qinfo) {
		dev_err(&master->dev, "%s(): create queue info failed\n",
		        __func__);
		ret = -ENOMEM;
		goto cleanup;
	}

	qinfo->dev = &spi->dev;

	qinfo->hw_priv = spi;
	qinfo->hw_ops = &hw_ops;

	mutex_init(&qinfo->mutex);
	INIT_DELAYED_WORK(&qinfo->irq_delayed_work, mt7697q_irq_delayed_work);
	INIT_WORK(&qinfo->irq_work, mt7697q_irq_work);

	qinfo->irq_workq = alloc_workqueue(DRVNAME"wq",
	                                   WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
	if (!qinfo->irq_workq) {
		dev_err(qinfo->dev, "%s(): alloc_workqueue() failed\n",
		        __func__);
		ret = -ENOMEM;
		goto cleanup;
	}

	qinfo->gpio_pin = MT7697_SPI_INTR_GPIO_PIN;
	ret = gpio_request(qinfo->gpio_pin, MT7697_SPI_GPIO_IRQ_NAME);
	if (ret < 0) {
		if (ret != -EBUSY) {
			dev_err(qinfo->dev, "%s(): gpio_request() failed(%d)",
			        __func__, ret);
			goto failed_workqueue;
		}

		qinfo->irq = gpio_to_irq(qinfo->gpio_pin);
		qinfo->gpio_pin = MT7697_SPI_INTR_GPIO_PIN_INVALID;
	} else {
		gpio_direction_input(qinfo->gpio_pin);
		qinfo->irq = gpio_to_irq(qinfo->gpio_pin);
	}

	dev_info(qinfo->dev, "%s(): request irq(%d)\n", __func__, qinfo->irq);
	ret = request_irq(qinfo->irq, mt7697q_isr, 0, DRVNAME, qinfo);
	if (ret < 0) {
		dev_err(qinfo->dev, "%s(): request_irq() failed(%d)",
		        __func__, ret);
		goto failed_gpio_req;
	}

	irq_set_irq_type(qinfo->irq, IRQ_TYPE_EDGE_BOTH);

	spi_set_drvdata(spi, qinfo);

	dev_info(qinfo->dev, "%s(): '%s' initialized\n", __func__, DRVNAME);
	return 0;

failed_gpio_req:
	if (qinfo->gpio_pin > 0) gpio_free(qinfo->gpio_pin);

failed_workqueue:
	destroy_workqueue(qinfo->irq_workq);

cleanup:
	if (qinfo) kfree(qinfo);
	return ret;
}
static int __init p1852_sku8_panel_init(void)
{
	int err;
	struct resource *res;
	struct platform_device *phost1x = NULL;
	bool is_dt = of_have_populated_dt();

	p1852_carveouts[1].base = tegra_carveout_start;
	p1852_carveouts[1].size = tegra_carveout_size;
	/* sku 8 has primary RGB out and secondary HDMI out */
	tegra_disp1_device.dev.platform_data = &p1852_disp1_pdata;
	tegra_disp2_device.dev.platform_data = &p1852_hdmi_pdata;

	err = platform_add_devices(p1852_gfx_devices,
				ARRAY_SIZE(p1852_gfx_devices));

#ifdef CONFIG_TEGRA_GRHOST
	if (!is_dt)
		phost1x = tegra3_register_host1x_devices();
	else
		phost1x = to_platform_device(bus_find_device_by_name(
			&platform_bus_type, NULL, "host1x"));
	if (!phost1x) {
		pr_err("host1x devices registration failed\n");
		return -EINVAL;
	}
#endif

#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC)
	res = platform_get_resource_byname(&tegra_disp1_device,
					 IORESOURCE_MEM, "fbmem");
	if (res) {
		res->start = tegra_fb_start;
		res->end = tegra_fb_start + tegra_fb_size - 1;
	}

	/*
	 * If the bootloader fb is valid, copy it to the fb, or else
	 * clear fb to avoid garbage on dispaly1.
	 */
	if (tegra_bootloader_fb_size)
		__tegra_move_framebuffer(&p1852_nvmap_device,
				tegra_fb_start, tegra_bootloader_fb_start,
				min(tegra_fb_size, tegra_bootloader_fb_size));
	else
		__tegra_clear_framebuffer(&p1852_nvmap_device,
				tegra_fb_start, tegra_fb_size);

	if (!err) {
		tegra_disp1_device.dev.parent = &phost1x->dev;
		err = platform_device_register(&tegra_disp1_device);
	}

	res = platform_get_resource_byname(&tegra_disp2_device,
					 IORESOURCE_MEM, "fbmem");
	if (res) {
		res->start = tegra_fb2_start;
		res->end = tegra_fb2_start + tegra_fb2_size - 1;
	}

	/*
	 * If the bootloader fb2 is valid, copy it to the fb2, or else
	 * clear fb2 to avoid garbage on dispaly2.
	 */
	if (tegra_bootloader_fb2_size)
		__tegra_move_framebuffer(&p1852_nvmap_device,
			tegra_fb2_start, tegra_bootloader_fb2_start,
			min(tegra_fb2_size, tegra_bootloader_fb2_size));
	else
		__tegra_clear_framebuffer(&p1852_nvmap_device,
					  tegra_fb2_start, tegra_fb2_size);

	if (!err) {
		tegra_disp2_device.dev.parent = &phost1x->dev;
		err = platform_device_register(&tegra_disp2_device);
	}
#endif

#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_NVAVP)
	if (!err) {
		nvavp_device.dev.parent = &phost1x->dev;
		err = platform_device_register(&nvavp_device);
	}
#endif
	return err;
}
Ejemplo n.º 12
0
static int __init add_nxtts_device_to_bus(void)
{
	struct spi_master *spi_master;
	struct spi_device *spi_device;
	struct device *pdev;
	char buff[64];
	int status = 0;

	/* This call returns a refcounted pointer to the relevant spi_master - the caller must release this pointer(device_put()) */	
	spi_master = spi_busnum_to_master(SPI_BUS);
	if (!spi_master) {
		printk(KERN_ALERT "spi_busnum_to_master(%d) returned NULL\n", SPI_BUS);
		printk(KERN_ALERT "Missing modprobe omap2_mcspi?\n");
		return -1;
	}

	spi_device = spi_alloc_device(spi_master);
	if (!spi_device) {
		printk(KERN_ALERT "spi_alloc_device() failed\n");
		return -1;
	}

	spi_device->chip_select = SPI_BUS_CS0;

	/* Check whether this SPI bus.cs is already claimed */
	/* snprintf the c-way of formatting a string */
	snprintf(buff, sizeof(buff), "%s.%u", dev_name(&spi_device->master->dev), spi_device->chip_select);

	pdev = bus_find_device_by_name(spi_device->dev.bus, NULL, buff);
 	if (pdev) {
		/* We are not going to use this spi_device, so free it. Since spi_device is not added then decrement the refcount */ 
		spi_dev_put(spi_device);

		/* 
		 * There is already a device configured for this bus.cs  
		 * It is okay if it us, otherwise complain and fail.
		 */
		if (pdev->driver && pdev->driver->name && strcmp(DEVICE_NAME, pdev->driver->name)) {
			printk(KERN_ALERT "Driver [%s] already registered for %s\n", pdev->driver->name, buff);
			status = -1;
		} 
	} else {
		spi_device->max_speed_hz = SPI_BUS_SPEED;
		spi_device->mode = SPI_MODE_0;
		spi_device->bits_per_word = SPI_BITS_PER_WORD;
		spi_device->irq = -1;
		spi_device->controller_state = NULL;
		spi_device->controller_data = NULL;
		strlcpy(spi_device->modalias, DEVICE_NAME, SPI_NAME_SIZE);

		status = spi_add_device(spi_device);		
		if (status < 0) {
			/* If spi_device is not added then decrement the refcount */	
			spi_dev_put(spi_device);
			printk(KERN_ALERT "spi_add_device() failed: %d\n", status);		
		}				
	}
	/* See comment for spi_busnum_to_master */
	put_device(&spi_master->dev);

	return status;
}