int main(int argc, char *argv[])
{
	int mb = -1;
	uint32_t gvp = NULL;
	unsigned *addr = NULL;
	unsigned off;
	int val;

	if (argc != 2) {
		fprintf(stderr, "error: Invalid the number of the arguments\n");
		usage(argv[0]);
		exit(EXIT_FAILURE);
	}

	off = 0; /* 0 is for the activity LED. */
	val = atoi(argv[1]);

	mb = rpi_firmware_open();

	rpi_firmware_property(mb, RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF, &gvp, sizeof(gvp));
	addr = mapmem_cpu(BUS_TO_PHYS(gvp), 4096);
	gpio_set(addr, off, val);
	unmapmem_cpu(addr, 4096);
	addr = NULL;

	rpi_firmware_close(mb);
	mb = -1;

	return 0;
}
Пример #2
0
/*
 * Asks the firmware to enable or disable power on a specific power
 * domain.
 */
static int rpi_firmware_set_power(struct rpi_power_domain *rpi_domain, bool on)
{
	struct rpi_power_domain_packet packet;

	packet.domain = rpi_domain->domain;
	packet.on = on;
	return rpi_firmware_property(rpi_domain->fw,
				     rpi_domain->old_interface ?
				     RPI_FIRMWARE_SET_POWER_STATE :
				     RPI_FIRMWARE_SET_DOMAIN_STATE,
				     &packet, sizeof(packet));
}
Пример #3
0
/*
 * Detects whether the firmware supports the new power domains interface.
 *
 * The firmware doesn't actually return an error on an unknown tag,
 * and just skips over it, so we do the detection by putting an
 * unexpected value in the return field and checking if it was
 * unchanged.
 */
static bool
rpi_has_new_domain_support(struct rpi_power_domains *rpi_domains)
{
	struct rpi_power_domain_packet packet;
	int ret;

	packet.domain = RPI_POWER_DOMAIN_ARM;
	packet.on = ~0;

	ret = rpi_firmware_property(rpi_domains->fw,
				    RPI_FIRMWARE_GET_DOMAIN_STATE,
				    &packet, sizeof(packet));

	return ret == 0 && packet.on != ~0;
}
Пример #4
0
static int bcm2835_cpufreq_clock_property(u32 tag, u32 id, u32 *val)
{
	struct rpi_firmware *fw = rpi_firmware_get(NULL);
	struct {
		u32 id;
		u32 val;
	} packet;
	int ret;

	packet.id = id;
	packet.val = *val;
	ret = rpi_firmware_property(fw, tag, &packet, sizeof(packet));
	if (ret)
		return ret;

	*val = packet.val;

	return 0;
}
Пример #5
0
static int bcm2835_thermal_get_property(struct thermal_zone_device *tz,
					unsigned long *temp, u32 tag)
{
	struct rpi_firmware *fw = tz->devdata;
	struct {
		u32 id;
		u32 val;
	} packet;
	int ret;

	*temp = 0;
	packet.id = 0;
	ret = rpi_firmware_property(fw, tag, &packet, sizeof(packet));
	if (ret) {
		dev_err(&tz->device, "Failed to get temperature\n");
		return ret;
	}

	*temp = packet.val;
	dev_dbg(&tz->device, "%stemp=%lu\n",
		tag == RPI_FIRMWARE_GET_MAX_TEMPERATURE ? "max" : "", *temp);

	return 0;
}
Пример #6
0
int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state)
{
	struct device *dev = &pdev->dev;
	struct rpi_firmware *fw = platform_get_drvdata(pdev);
	VCHIQ_SLOT_ZERO_T *vchiq_slot_zero;
	struct resource *res;
	void *slot_mem;
	dma_addr_t slot_phys;
	u32 channelbase;
	int slot_mem_size, frag_mem_size;
	int err, irq, i;

	g_virt_to_bus_offset = virt_to_dma(dev, (void *)0);

	(void)of_property_read_u32(dev->of_node, "cache-line-size",
				   &g_cache_line_size);
	g_fragments_size = 2 * g_cache_line_size;

	/* Allocate space for the channels in coherent memory */
	slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE);
	frag_mem_size = PAGE_ALIGN(g_fragments_size * MAX_FRAGMENTS);

	slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size,
				       &slot_phys, GFP_KERNEL);
	if (!slot_mem) {
		dev_err(dev, "could not allocate DMA memory\n");
		return -ENOMEM;
	}

	WARN_ON(((int)slot_mem & (PAGE_SIZE - 1)) != 0);

	vchiq_slot_zero = vchiq_init_slots(slot_mem, slot_mem_size);
	if (!vchiq_slot_zero)
		return -EINVAL;

	vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] =
		(int)slot_phys + slot_mem_size;
	vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] =
		MAX_FRAGMENTS;

	g_fragments_base = (char *)slot_mem + slot_mem_size;
	slot_mem_size += frag_mem_size;

	g_free_fragments = g_fragments_base;
	for (i = 0; i < (MAX_FRAGMENTS - 1); i++) {
		*(char **)&g_fragments_base[i*g_fragments_size] =
			&g_fragments_base[(i + 1)*g_fragments_size];
	}
	*(char **)&g_fragments_base[i * g_fragments_size] = NULL;
	sema_init(&g_free_fragments_sema, MAX_FRAGMENTS);

	if (vchiq_init_state(state, vchiq_slot_zero, 0) != VCHIQ_SUCCESS)
		return -EINVAL;

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

	irq = platform_get_irq(pdev, 0);
	if (irq <= 0) {
		dev_err(dev, "failed to get IRQ\n");
		return irq;
	}

	err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL,
			       "VCHIQ doorbell", state);
	if (err) {
		dev_err(dev, "failed to register irq=%d\n", irq);
		return err;
	}

	/* Send the base address of the slots to VideoCore */
	channelbase = slot_phys;
	err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT,
				    &channelbase, sizeof(channelbase));
	if (err || channelbase) {
		dev_err(dev, "failed to set channelbase\n");
		return err ? : -ENXIO;
	}