>From 8b5eaecf647d3c71a7d0a70b7d0e68d06ed03988 Mon Sep 17 00:00:00 2001
From: Rudolf Marek <r.marek@assembler.cz>
Date: Sun, 27 May 2018 12:44:46 +0200
Subject: [PATCH] Add basic JMICRON controller support

Change-Id: Ibe6d39b25f0d096ae8838f2a02be97ae146f0405
Signed-off-by: Rudolf Marek <r.marek@assembler.cz>
---
 Makefile     | 20 ++++++++++++
 flashrom.c   | 12 ++++++++
 jmicron.c    | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 programmer.h |  9 ++++++
 4 files changed, 140 insertions(+)
 create mode 100644 jmicron.c

diff --git a/Makefile b/Makefile
index 5bd7158..1bddd6a 100644
--- a/Makefile
+++ b/Makefile
@@ -239,6 +239,11 @@ UNSUPPORTED_FEATURES += CONFIG_IT8212=yes
 else
 override CONFIG_IT8212 = no
 endif
+ifeq ($(CONFIG_JMICRON), yes)
+UNSUPPORTED_FEATURES += CONFIG_JMICRON=yes
+else
+override CONFIG_JMICRON = no
+endif
 ifeq ($(CONFIG_DRKAISER), yes)
 UNSUPPORTED_FEATURES += CONFIG_DRKAISER=yes
 else
@@ -506,6 +511,11 @@ UNSUPPORTED_FEATURES += CONFIG_IT8212=yes
 else
 override CONFIG_IT8212 = no
 endif
+ifeq ($(CONFIG_JMICRON), yes)
+UNSUPPORTED_FEATURES += CONFIG_JMICRON=yes
+else
+override CONFIG_JMICRON = no
+endif
 endif
 
 ###############################################################################
@@ -629,6 +639,9 @@ CONFIG_LINUX_SPI ?= yes
 # Always enable ITE IT8212F PATA controllers for now.
 CONFIG_IT8212 ?= yes
 
+# Always enable JMICRON for now.
+CONFIG_JMICRON ?= yes
+
 # Winchiphead CH341A
 CONFIG_CH341A_SPI ?= yes
 
@@ -669,6 +682,7 @@ override CONFIG_ATAHPT = no
 override CONFIG_ATAVIA = no
 override CONFIG_ATAPROMISE = no
 override CONFIG_IT8212 = no
+override CONFIG_JMICRON = no
 override CONFIG_DRKAISER = no
 override CONFIG_NICREALTEK = no
 override CONFIG_NICNATSEMI = no
@@ -806,6 +820,12 @@ PROGRAMMER_OBJS += it8212.o
 NEED_LIBPCI += CONFIG_IT8212
 endif
 
+ifeq ($(CONFIG_JMICRON), yes)
+FEATURE_CFLAGS += -D'CONFIG_JMICRON=1'
+PROGRAMMER_OBJS += jmicron.o
+NEED_LIBPCI += CONFIG_JMICRON
+endif
+
 ifeq ($(CONFIG_FT2232_SPI), yes)
 # This is a totally ugly hack.
 FEATURE_CFLAGS += $(call debug_shell,grep -q "FTDISUPPORT := yes" .features && printf "%s" "-D'CONFIG_FT2232_SPI=1'")
diff --git a/flashrom.c b/flashrom.c
index 4fe1843..ace2f04 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -208,6 +208,18 @@ const struct programmer_entry programmer_table[] = {
 	},
 #endif
 
+#if CONFIG_JMICRON == 1
+	{
+		.name			= "jmicron",
+		.type			= PCI,
+		.devs.dev		= devs_jmicron,
+		.init			= jmicron_init,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+		.delay			= internal_delay,
+	},
+#endif
+
 #if CONFIG_FT2232_SPI == 1
 	{
 		.name			= "ft2232_spi",
diff --git a/jmicron.c b/jmicron.c
new file mode 100644
index 0000000..6c65129
--- /dev/null
+++ b/jmicron.c
@@ -0,0 +1,99 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2011 Carl-Daniel Hailfinger
+ * Copyright (C) 2012 Kyösti Mälkki <kyosti.malkki@gmail.com>
+ * Copyright (C) 2018 Rudolf Marek <r.marek@assembler.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include "flash.h"
+#include "programmer.h"
+#include "hwaccess.h"
+
+static uint8_t *jmicron_bar = NULL;
+
+const struct dev_entry devs_jmicron[] = {
+	{0x197b, 0x2361, NT, "JMICRON", "JMB361"}, /* Also contains SPI interface, currently unsupported */
+	{0x197b, 0x2363, OK, "JMICRON", "JMB363"},
+	{0x197b, 0x2366, NT, "JMICRON", "JMB366"},
+	{},
+};
+
+#define JMICRON_MEMMAP_SIZE (64 * 1024)
+#define JMICRON_MEMMAP_MASK (JMICRON_MEMMAP_SIZE - 1)
+
+static void jmicron_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr);
+static uint8_t jmicron_chip_readb(const struct flashctx *flash, const chipaddr addr);
+static const struct par_master par_master_jmicron = {
+		.chip_readb		= jmicron_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= fallback_chip_readn,
+		.chip_writeb		= jmicron_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+};
+
+int jmicron_init(void)
+{
+	uint8_t old;
+	if (rget_io_perms())
+		return 1;
+
+	struct pci_dev *dev = pcidev_init(devs_jmicron, PCI_ROM_ADDRESS);
+	if (!dev)
+		return 1;
+
+	/* This initialization sequence is based on JMICRON DOS utillity */
+	old = pci_read_byte(dev, 0x48);
+	rpci_write_byte(dev, 0x48, old | 0x1);
+
+	old = pci_read_byte(dev, 0x49);
+	rpci_write_byte(dev, 0x49, old | 0x1);
+
+	old = pci_read_byte(dev, 0x43);
+	if (!(old & 0x80)) {
+		rpci_write_byte(dev, 0x43, old | 0x80);
+	}
+
+	/* Bit 0 is address decode enable, 17-31 the base address, everything else reserved/zero. */
+	uint32_t io_base_addr = pcidev_readbar(dev, PCI_ROM_ADDRESS) & 0xFFFFFFFE;
+	if (!io_base_addr)
+		return 1;
+
+	jmicron_bar = rphysmap("JMicron flash", io_base_addr, JMICRON_MEMMAP_SIZE);
+	if (jmicron_bar == ERROR_PTR)
+		return 1;
+
+	/* Restore ROM BAR decode state automatically at shutdown. */
+	rpci_write_long(dev, PCI_ROM_ADDRESS, io_base_addr | 0x01);
+
+	max_rom_decode.parallel = JMICRON_MEMMAP_SIZE;
+	register_par_master(&par_master_jmicron, BUS_PARALLEL);
+	return 0;
+}
+
+static void jmicron_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
+{
+	pci_mmio_writeb(val, jmicron_bar + (addr & JMICRON_MEMMAP_MASK));
+}
+
+static uint8_t jmicron_chip_readb(const struct flashctx *flash, const chipaddr addr)
+{
+	return pci_mmio_readb(jmicron_bar + (addr & JMICRON_MEMMAP_MASK));
+}
diff --git a/programmer.h b/programmer.h
index a98b713..f55579d 100644
--- a/programmer.h
+++ b/programmer.h
@@ -63,6 +63,9 @@ enum programmer {
 #if CONFIG_IT8212 == 1
 	PROGRAMMER_IT8212,
 #endif
+#if CONFIG_JMICRON == 1
+	PROGRAMMER_JMICRON,
+#endif
 #if CONFIG_FT2232_SPI == 1
 	PROGRAMMER_FT2232_SPI,
 #endif
@@ -484,6 +487,12 @@ int it8212_init(void);
 extern const struct dev_entry devs_it8212[];
 #endif
 
+/* jmicron.c */
+#if CONFIG_JMICRON == 1
+int jmicron_init(void);
+extern const struct dev_entry devs_jmicron[];
+#endif
+
 /* ft2232_spi.c */
 #if CONFIG_FT2232_SPI == 1
 int ft2232_spi_init(void);
-- 
2.7.4

