diff --git a/tools/Makefile b/tools/Makefile
index 9c26879987bbcd96acbff6cf33a357c20384efa0..fb3c54a4d780798b29722c1bd3577799b3975d8a 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -1,7 +1,7 @@
 CFLAGS = -Wall -ggdb
 LDFLAGS = -lutil
 ALL    = genraminit genramvhd genrammif wrpc-uart-sw
-ALL   += wrpc-w1-read #wrpc-w1-write
+ALL   += wrpc-w1-read wrpc-w1-write
 
 AS		= as
 LD		= ld
@@ -21,6 +21,8 @@ all:	$(ALL)
 wrpc-w1-read: wrpc-w1-read.c w1-host/libw1.a
 	$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
 
+wrpc-w1-write: wrpc-w1-write.c w1-host/libw1.a
+	$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
 w1-host/libw1.a:
 	$(MAKE) -C w1-host
 
diff --git a/tools/wrpc-w1-write.c b/tools/wrpc-w1-write.c
new file mode 100644
index 0000000000000000000000000000000000000000..5c9a7834cdbe450019a1972a11c45dffe923ce01
--- /dev/null
+++ b/tools/wrpc-w1-write.c
@@ -0,0 +1,255 @@
+/*
+ * This work is part of the White Rabbit project
+ *
+ * Copyright (C) 2013 CERN (www.cern.ch)
+ * Author: Alessandro Rubini <rubini@gnudd.com>
+ * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
+ *
+ * Released according to the GNU GPL, version 2 or any later version.
+ */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "w1-host/w1.h"
+
+#define SPEC_W1_OFFSET 0x20600 /* from "sdb" on the shell, current gateware */
+
+#define MAX_DEVICES		8		/* no alloc, me lazy */
+
+static struct spec_pci_id {
+	unsigned pci_v;
+	unsigned pci_d;
+} spec_devices[] = {
+	{ 0x10dc /* CERN   */, 0x018d /* SPEC   */ },
+	{ 0x1a39 /* Gennum */, 0x0004 /* GN4124 */ },
+	{ 0, },
+};
+
+struct spec_device {
+	void *mapaddr;
+	int mapsize;
+	int busid;
+};
+
+static struct spec_device devs[MAX_DEVICES];
+
+char *prgname;
+int verbose;
+
+/* sames name as in ./dev because we reuse lm32 code */
+void *BASE_ONEWIRE;
+struct w1_bus wrpc_w1_bus;
+
+
+static int spec_write_w1(struct spec_device *spec, int w1base, int w1len)
+{
+	struct w1_dev *d;
+	uint8_t buf[w1len];
+	int i;
+
+	BASE_ONEWIRE = spec->mapaddr + SPEC_W1_OFFSET;
+	w1_scan_bus(&wrpc_w1_bus);
+
+	if (verbose) { /* code borrowed from dev/w1.c -- "w1" shell command */
+		for (i = 0; i < W1_MAX_DEVICES; i++) {
+			d = wrpc_w1_bus.devs + i;
+			if (d->rom)
+				fprintf(stderr, "device %i: %08x%08x\n", i,
+					(int)(d->rom >> 32), (int)d->rom);
+		}
+	}
+
+	if (verbose) {
+		fprintf(stderr, "Writing device on bus %i: "
+			"offset %i (0x%x), len %i\n", spec->busid,
+			w1base, w1base, w1len);
+	}
+
+	if (isatty(fileno(stdin)))
+		fprintf(stderr, "Reading from stdin, please type the data\n");
+	i = fread(buf, 1, w1len, stdin);
+	if (i != w1len) {
+		fprintf(stderr, "%s: read error (%i, expeted %i)\n", prgname,
+			i, w1len);
+		return 1;
+	}
+	i = w1_write_eeprom_bus(&wrpc_w1_bus, w1base, buf, w1len);
+	if (i != w1len) {
+		fprintf(stderr, "Tried to write %i bytes, retval %i\n",
+			w1len, i);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * What follows is mostly generic, should be librarized in a way
+ */
+
+/* Access a PCI device, mmap and so on */
+static void *spec_access_pci(char *name, int index)
+{
+	struct spec_device *dev = devs + index;
+	char path[PATH_MAX];
+	struct stat stbuf;
+	int fd;
+
+	memset(dev, 0, sizeof(*dev));
+	sprintf(path, "/sys/bus/pci/devices/%s/resource0", name);
+	if ((fd = open(path, O_RDWR | O_SYNC)) < 0) {
+		fprintf(stderr, "%s: %s: %s\n", prgname, path,
+			strerror(errno));
+		return NULL;
+	}
+	fstat(fd, &stbuf);
+	dev->mapsize = stbuf.st_size;
+	dev->mapaddr = mmap(0, stbuf.st_size,
+			    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+	close(fd);
+	if (dev->mapaddr == MAP_FAILED) {
+		fprintf(stderr, "%s: mmap(%s): %s\n", prgname, path,
+			strerror(errno));
+		return NULL;
+	}
+	if (sscanf(name, "%*x:%x", &dev->busid) != 1)
+		return NULL;
+	return dev->mapaddr;
+}
+
+/* Scan PCI space for vendor and device; return number of successes */
+static int spec_scan_pci(struct spec_pci_id *id, struct spec_device *arr,
+			int alen)
+{
+	char path[PATH_MAX];
+	FILE *f;
+	struct dirent **namelist;
+	int i, j, n, ndevs;
+	unsigned v, d;
+
+	n = scandir("/sys/bus/pci/devices", &namelist, 0, 0);
+	if (n < 0) {
+		fprintf(stderr, "%s: /sys/bus/pci/devices: %s\n", prgname,
+			strerror(errno));
+		return -1;
+	}
+
+	for (i = ndevs = 0; i < n; i++) {
+		if (namelist[i]->d_name[0] == '.')
+			continue;
+		/* check vendor */
+		sprintf(path, "/sys/bus/pci/devices/%s/vendor",
+			namelist[i]->d_name);
+		f = fopen(path, "r");
+		if (!f) {
+			fprintf(stderr, "%s: %s: %s\n", prgname, path,
+				strerror(errno));
+			continue;
+		}
+		if (fscanf(f, "%i", &v) != 1)
+			continue;
+		fclose(f);
+
+		/* check device */
+		sprintf(path, "/sys/bus/pci/devices/%s/device",
+			namelist[i]->d_name);
+		f = fopen(path, "r");
+		if (!f) {
+			fprintf(stderr, "%s: %s: %s\n", prgname, path,
+				strerror(errno));
+			continue;
+		}
+		if (fscanf(f, "%i", &d) != 1)
+			continue;
+		fclose(f);
+
+		for (j = 0; id[j].pci_v; j++)
+			if (id[j].pci_v == v && id[j].pci_d == d)
+				break;
+		if (!spec_devices[j].pci_v)
+			continue; /* not found in whole array */
+
+		/* Ok, so this is ours. Celebrate, and open it */
+		if (verbose)
+			fprintf(stderr, "%s: found device %04x:%04x: %s\n",
+				prgname, v, d, namelist[i]->d_name);
+
+		if (ndevs == alen) {
+			fprintf(stderr, "%s: array overflow, ignoring card\n",
+				prgname);
+			continue;
+		}
+		if (spec_access_pci(namelist[i]->d_name, ndevs) == NULL)
+			continue;
+		ndevs++;
+	}
+	return ndevs;
+}
+
+static int help(void)
+{
+	fprintf(stderr, "%s: Use: \"%s [-v] [-b <bus>] <addr> <len>\n",
+		prgname, prgname);
+	return 1;
+}
+
+int main(int argc, char **argv)
+{
+	int ndev, i, c, bus = -1;
+	struct spec_device *spec = NULL;
+	prgname = argv[0];
+
+	while ((c = getopt(argc, argv, "b:v")) != -1) {
+		switch(c) {
+		case 'b':
+			sscanf(optarg, "%i", &bus);
+			break;
+		case 'v':
+			verbose++;
+			break;
+		default:
+			exit(help());
+		}
+	}
+	if (optind != argc - 2)
+		exit(help());
+
+	/* find which one to use */
+	ndev = spec_scan_pci(spec_devices, devs, MAX_DEVICES);
+	if (ndev < 1) {
+		fprintf(stderr, "%s: no suitable PCI devices\n", prgname);
+		exit(1);
+	}
+	if (bus == -1 && ndev == 1) {
+		spec = devs;
+	} else if (bus == -1) {
+		fprintf(stderr, "%s: several devices found, please choose:\n",
+			prgname);
+		for (i = 0; i < ndev; i++) {
+			fprintf(stderr, "   -b %i\n", devs[i].busid);
+		}
+		exit(1);
+	} else {
+		for (i = 0; i < ndev; i++)
+			if (bus == devs[i].busid)
+				break;
+		if (i == ndev) {
+			fprintf(stderr, "%s: no device on bus %i\n", prgname,
+				bus);
+			exit(1);
+		}
+		spec = devs + i;
+	}
+
+	i = spec_write_w1(spec, atoi(argv[optind]), atoi(argv[optind + 1]));
+	return i;
+}