Пример #1
0
static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
{
	if (p->dev->of_node) {
		struct device_node *np = p->dev->of_node;
		int id;

		/* get index of serial line, if found in DT aliases */
		id = of_alias_get_id(np, "serial");
		if (id >= 0)
			p->line = id;
#ifdef CONFIG_64BIT
		if (of_device_is_compatible(np, "cavium,octeon-3860-uart")) {
			p->serial_in = dw8250_serial_inq;
			p->serial_out = dw8250_serial_outq;
			p->flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
			p->type = PORT_OCTEON;
			data->usr_reg = 0x27;
			data->skip_autocfg = true;
		}
#endif
		if (of_device_is_big_endian(p->dev->of_node)) {
			p->iotype = UPIO_MEM32BE;
			p->serial_in = dw8250_serial_in32be;
			p->serial_out = dw8250_serial_out32be;
		}
	} else if (has_acpi_companion(p->dev)) {
		const struct acpi_device_id *id;

		id = acpi_match_device(p->dev->driver->acpi_match_table,
				       p->dev);
		if (id && !strcmp(id->id, "APMC0D08")) {
			p->iotype = UPIO_MEM32;
			p->regshift = 2;
			p->serial_in = dw8250_serial_in32;
			data->uart_16550_compatible = true;
		}
		p->set_termios = dw8250_set_termios;
	}

	/* Platforms with iDMA */
	if (platform_get_resource_byname(to_platform_device(p->dev),
					 IORESOURCE_MEM, "lpss_priv")) {
		p->set_termios = dw8250_set_termios;
		data->dma.rx_param = p->dev->parent;
		data->dma.tx_param = p->dev->parent;
		data->dma.fn = dw8250_idma_filter;
	}
}
Пример #2
0
/*
 * Fill a struct uart_port for a given device node
 */
static int of_platform_serial_setup(struct platform_device *ofdev,
			int type, struct uart_port *port,
			struct of_serial_info *info)
{
	struct resource resource;
	struct device_node *np = ofdev->dev.of_node;
	u32 clk, spd, prop;
	int ret;

	memset(port, 0, sizeof *port);
	if (of_property_read_u32(np, "clock-frequency", &clk)) {

		/* Get clk rate through clk driver if present */
		info->clk = devm_clk_get(&ofdev->dev, NULL);
		if (IS_ERR(info->clk)) {
			dev_warn(&ofdev->dev,
				"clk or clock-frequency not defined\n");
			return PTR_ERR(info->clk);
		}

		ret = clk_prepare_enable(info->clk);
		if (ret < 0)
			return ret;

		clk = clk_get_rate(info->clk);
	}
	/* If current-speed was set, then try not to change it. */
	if (of_property_read_u32(np, "current-speed", &spd) == 0)
		port->custom_divisor = clk / (16 * spd);

	ret = of_address_to_resource(np, 0, &resource);
	if (ret) {
		dev_warn(&ofdev->dev, "invalid address\n");
		goto out;
	}

	spin_lock_init(&port->lock);
	port->mapbase = resource.start;
	port->mapsize = resource_size(&resource);

	/* Check for shifted address mapping */
	if (of_property_read_u32(np, "reg-offset", &prop) == 0)
		port->mapbase += prop;

	/* Check for registers offset within the devices address range */
	if (of_property_read_u32(np, "reg-shift", &prop) == 0)
		port->regshift = prop;

	/* Check for fifo size */
	if (of_property_read_u32(np, "fifo-size", &prop) == 0)
		port->fifosize = prop;

	/* Check for a fixed line number */
	ret = of_alias_get_id(np, "serial");
	if (ret >= 0)
		port->line = ret;

	port->irq = irq_of_parse_and_map(np, 0);
	port->iotype = UPIO_MEM;
	if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
		switch (prop) {
		case 1:
			port->iotype = UPIO_MEM;
			break;
		case 2:
			port->iotype = UPIO_MEM16;
			break;
		case 4:
			port->iotype = of_device_is_big_endian(np) ?
				       UPIO_MEM32BE : UPIO_MEM32;
			break;
		default:
			dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
				 prop);
			ret = -EINVAL;
			goto out;
		}
	}

	port->type = type;
	port->uartclk = clk;
	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
		| UPF_FIXED_PORT | UPF_FIXED_TYPE;

	if (of_find_property(np, "no-loopback-test", NULL))
		port->flags |= UPF_SKIP_TEST;

	port->dev = &ofdev->dev;

	switch (type) {
	case PORT_TEGRA:
		port->handle_break = tegra_serial_handle_break;
		break;

	case PORT_RT2880:
		port->iotype = UPIO_AU;
		break;
	}

	if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) &&
	    (of_device_is_compatible(np, "fsl,ns16550") ||
	     of_device_is_compatible(np, "fsl,16550-FIFO64")))
		port->handle_irq = fsl8250_handle_irq;

	return 0;
out:
	if (info->clk)
		clk_disable_unprepare(info->clk);
	return ret;
}
Пример #3
0
int bcm_qspi_probe(struct platform_device *pdev,
		   struct bcm_qspi_soc_intc *soc_intc)
{
	struct device *dev = &pdev->dev;
	struct bcm_qspi *qspi;
	struct spi_master *master;
	struct resource *res;
	int irq, ret = 0, num_ints = 0;
	u32 val;
	const char *name = NULL;
	int num_irqs = ARRAY_SIZE(qspi_irq_tab);

	/* We only support device-tree instantiation */
	if (!dev->of_node)
		return -ENODEV;

	if (!of_match_node(bcm_qspi_of_match, dev->of_node))
		return -ENODEV;

	master = spi_alloc_master(dev, sizeof(struct bcm_qspi));
	if (!master) {
		dev_err(dev, "error allocating spi_master\n");
		return -ENOMEM;
	}

	qspi = spi_master_get_devdata(master);
	qspi->pdev = pdev;
	qspi->trans_pos.trans = NULL;
	qspi->trans_pos.byte = 0;
	qspi->trans_pos.mspi_last_trans = true;
	qspi->master = master;

	master->bus_num = -1;
	master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_RX_DUAL | SPI_RX_QUAD;
	master->setup = bcm_qspi_setup;
	master->transfer_one = bcm_qspi_transfer_one;
	master->spi_flash_read = bcm_qspi_flash_read;
	master->cleanup = bcm_qspi_cleanup;
	master->dev.of_node = dev->of_node;
	master->num_chipselect = NUM_CHIPSELECT;

	qspi->big_endian = of_device_is_big_endian(dev->of_node);

	if (!of_property_read_u32(dev->of_node, "num-cs", &val))
		master->num_chipselect = val;

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hif_mspi");
	if (!res)
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
						   "mspi");

	if (res) {
		qspi->base[MSPI]  = devm_ioremap_resource(dev, res);
		if (IS_ERR(qspi->base[MSPI])) {
			ret = PTR_ERR(qspi->base[MSPI]);
			goto qspi_resource_err;
		}
	} else {
		goto qspi_resource_err;
	}

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
	if (res) {
		qspi->base[BSPI]  = devm_ioremap_resource(dev, res);
		if (IS_ERR(qspi->base[BSPI])) {
			ret = PTR_ERR(qspi->base[BSPI]);
			goto qspi_resource_err;
		}
		qspi->bspi_mode = true;
	} else {
		qspi->bspi_mode = false;
	}

	dev_info(dev, "using %smspi mode\n", qspi->bspi_mode ? "bspi-" : "");

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cs_reg");
	if (res) {
		qspi->base[CHIP_SELECT]  = devm_ioremap_resource(dev, res);
		if (IS_ERR(qspi->base[CHIP_SELECT])) {
			ret = PTR_ERR(qspi->base[CHIP_SELECT]);
			goto qspi_resource_err;
		}
	}

	qspi->dev_ids = kcalloc(num_irqs, sizeof(struct bcm_qspi_dev_id),
				GFP_KERNEL);
	if (!qspi->dev_ids) {
		ret = -ENOMEM;
		goto qspi_resource_err;
	}

	for (val = 0; val < num_irqs; val++) {
		irq = -1;
		name = qspi_irq_tab[val].irq_name;
		if (qspi_irq_tab[val].irq_source == SINGLE_L2) {
			/* get the l2 interrupts */
			irq = platform_get_irq_byname(pdev, name);
		} else if (!num_ints && soc_intc) {
			/* all mspi, bspi intrs muxed to one L1 intr */
			irq = platform_get_irq(pdev, 0);
		}

		if (irq  >= 0) {
			ret = devm_request_irq(&pdev->dev, irq,
					       qspi_irq_tab[val].irq_handler, 0,
					       name,
					       &qspi->dev_ids[val]);
			if (ret < 0) {
				dev_err(&pdev->dev, "IRQ %s not found\n", name);
				goto qspi_probe_err;
			}

			qspi->dev_ids[val].dev = qspi;
			qspi->dev_ids[val].irqp = &qspi_irq_tab[val];
			num_ints++;
			dev_dbg(&pdev->dev, "registered IRQ %s %d\n",
				qspi_irq_tab[val].irq_name,
				irq);
		}
	}

	if (!num_ints) {
		dev_err(&pdev->dev, "no IRQs registered, cannot init driver\n");
		ret = -EINVAL;
		goto qspi_probe_err;
	}

	/*
	 * Some SoCs integrate spi controller (e.g., its interrupt bits)
	 * in specific ways
	 */
	if (soc_intc) {
		qspi->soc_intc = soc_intc;
		soc_intc->bcm_qspi_int_set(soc_intc, MSPI_DONE, true);
	} else {
		qspi->soc_intc = NULL;
	}

	qspi->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(qspi->clk)) {
		dev_warn(dev, "unable to get clock\n");
		ret = PTR_ERR(qspi->clk);
		goto qspi_probe_err;
	}

	ret = clk_prepare_enable(qspi->clk);
	if (ret) {
		dev_err(dev, "failed to prepare clock\n");
		goto qspi_probe_err;
	}

	qspi->base_clk = clk_get_rate(qspi->clk);
	qspi->max_speed_hz = qspi->base_clk / (QSPI_SPBR_MIN * 2);

	bcm_qspi_hw_init(qspi);
	init_completion(&qspi->mspi_done);
	init_completion(&qspi->bspi_done);
	qspi->curr_cs = -1;

	platform_set_drvdata(pdev, qspi);

	qspi->xfer_mode.width = -1;
	qspi->xfer_mode.addrlen = -1;
	qspi->xfer_mode.hp = -1;

	ret = devm_spi_register_master(&pdev->dev, master);
	if (ret < 0) {
		dev_err(dev, "can't register master\n");
		goto qspi_reg_err;
	}

	return 0;

qspi_reg_err:
	bcm_qspi_hw_uninit(qspi);
	clk_disable_unprepare(qspi->clk);
qspi_probe_err:
	kfree(qspi->dev_ids);
qspi_resource_err:
	spi_master_put(master);
	return ret;
}
Пример #4
0
static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
{
	struct device_node *dn = pdev->dev.of_node;
	struct brcmstb_gisb_arb_device *gdev;
	const struct of_device_id *of_id;
	struct resource *r;
	int err, timeout_irq, tea_irq;
	unsigned int num_masters, j = 0;
	int i, first, last;

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	timeout_irq = platform_get_irq(pdev, 0);
	tea_irq = platform_get_irq(pdev, 1);

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

	mutex_init(&gdev->lock);
	INIT_LIST_HEAD(&gdev->next);

	gdev->base = devm_ioremap_resource(&pdev->dev, r);
	if (IS_ERR(gdev->base))
		return PTR_ERR(gdev->base);

	of_id = of_match_node(brcmstb_gisb_arb_of_match, dn);
	if (!of_id) {
		pr_err("failed to look up compatible string\n");
		return -EINVAL;
	}
	gdev->gisb_offsets = of_id->data;
	gdev->big_endian = of_device_is_big_endian(dn);

	err = devm_request_irq(&pdev->dev, timeout_irq,
				brcmstb_gisb_timeout_handler, 0, pdev->name,
				gdev);
	if (err < 0)
		return err;

	err = devm_request_irq(&pdev->dev, tea_irq,
				brcmstb_gisb_tea_handler, 0, pdev->name,
				gdev);
	if (err < 0)
		return err;

	/* If we do not have a valid mask, assume all masters are enabled */
	if (of_property_read_u32(dn, "brcm,gisb-arb-master-mask",
				&gdev->valid_mask))
		gdev->valid_mask = 0xffffffff;

	/* Proceed with reading the litteral names if we agree on the
	 * number of masters
	 */
	num_masters = of_property_count_strings(dn,
			"brcm,gisb-arb-master-names");
	if (hweight_long(gdev->valid_mask) == num_masters) {
		first = ffs(gdev->valid_mask) - 1;
		last = fls(gdev->valid_mask) - 1;

		for (i = first; i < last; i++) {
			if (!(gdev->valid_mask & BIT(i)))
				continue;

			of_property_read_string_index(dn,
					"brcm,gisb-arb-master-names", j,
					&gdev->master_names[i]);
			j++;
		}
	}

	err = sysfs_create_group(&pdev->dev.kobj, &gisb_arb_sysfs_attr_group);
	if (err)
		return err;

	platform_set_drvdata(pdev, gdev);

	list_add_tail(&gdev->next, &brcmstb_gisb_arb_device_list);

#ifdef CONFIG_ARM
	hook_fault_code(22, brcmstb_bus_error_handler, SIGBUS, 0,
			"imprecise external abort");
#endif

	dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n",
			gdev->base, timeout_irq, tea_irq);

	return 0;
}